`as` keyword and casting

Godot Version

4.6

Question

Hi everyone!

I wrote a small extension of SpriteFrames holding animation offsets

class_name SpriteFramesEx
extends SpriteFrames

var offsets: Dictionary[String, Vector2]

I’ve created my SpriteFrames before designing the system around SpriteFramesEx, so I tried to cast them, but the cast set the result as null

func get_sprite_frames_ex(sprite_id: int) -> SpriteFramesEx:	
	# Sprite frames
	var sfe = _get_character_sprite_frames(sprite_id) 
	
	if sfe == null:
		return null

	print("sfe: %s" % sfe) # (res://world/characters/graphics/680/680.tres):<SpriteFrames#-9223371935335838899>
	sfe = sfe as SpriteFramesEx
	print("sfe %s:" % sfe) # <null>


	# Offsets
	var offset_dict = _get_character_sprite_metadata(sprite_id)
	for anim_name in offset_dict.keys():
		var anim = offset_dict.get(anim_name)
		sfe.offsets.set(anim_name, anim["offset"])

	return sfe

I have several options to work around, but I think I don’t get the as keyword right. Could someone explains why it doesn’t work, and when this keyword makes sense ?

Thanks by advance :grinning_face_with_smiling_eyes:

On the second line, what does _get_character_sprite_frames return?

If it returns a normal SpriteFrames, then that’s your issue.

The “as” keyword won’t magically turn one class into an entirely different class, the purpose of the as keyword is to tell the engine what that specific variable type should be. It won’t “change” it, so to speak.

You can only use the as keyword if the variable you are trying to use is already that class you are expecting, but your methods returned a more generic version of it, eg: SpriteFrames, but you know for a fact that that returned variable IS a SpriteFramesEx.

Further to what tibaverus says:

func _moo()->void: 
	var a:testA = testA.new()
	var b:testA = testB.new()
	
	print(a)  # testA
	print(b)  # testB
	print(a as testB)  #<null>
	print(b as testB)  #testB
	
	
class testA: 
	func _to_string() -> String:
		return "TestA"
class testB extends testA: 
	func _to_string() -> String:
		return "TestB"		

TestA
TestB
<null>
TestB

You need to understand the difference between static type (of an expression or variable) and dynamic type (of a value or object). Each object or value has a dynamic type. Each variable or expression has a static type. The static type of an expression or variable must match the dynamic type of the value or object that the variable stores or the expression evaluates to, but the static type can be less specific than the dynamic type. The ‘as’ keyword creates an expression of a more specific static type, but the dynamic type of the value must still match the static type of the expression or the expression evaluates to null.

Thank you for your answers ! I think I understand now the use of as