I was struggling to understand why the override of get_class() wasn’t working in another part of my code, since it was working just fine in my main script. And then, I figured out that the get_class() was only working 'cause I was calling it from a variable that contained the node I wanted to call get_class(). Attaching the node to a variable and then calling get_class() fixed my problem, but I still wanna understand why it doesn’t work if I call it directly from a node of my scene tree. That doesn’t makes sense to me. If someone can explain for me what’s happening, I’d appreciate. Here is my code:
var object = load("res://scenes/white's farm/weapons/pistol.tscn").instantiate()
func _ready():
add_child(object)
var child = get_child(-1)
print(get_child(-1).get_class()) #Gives wrong outcome
print(child.get_class()) #Gives right outcome
print(object.get_class()) #Gives right outcome
You’re right about get_class ignoring class_name declarations, that’s why I did override get_class() to return me my desired outcome, as it seems there’s no other way to do that. Also, thanks for the advice on using the “is” keyword, but in this case, I need to verify the String, as I’m using the outcome in a match statement. The “is” keyword only work with if/else, not with match statements unfortunately, and that’s why I’m using get_class() for comparing instead.
Btw, why did you highlight the “get_child(-1)”? Is it a bad way of getting a node or a bad practice? Thanks for helping me.
Switch you match to a few if/elifs and use is that will be the best way to accurately get the class with class_name extensions. You could make your own enum for types of blueprints if you really want to keep match.
I thought about doing an enum, but the problem is that I made this all over my scripts, so I don’t have plans to change it now, as it works fine. As I said before, I fixed my problem. I just made this post mainly to understand why it works this way:
var child = get_child(-1)
print(child.get_class())
But not this way:
print(get_child(-1).get_class())
I’m trying to figure out why this happens and maybe find a aswer that might help somebody else here in the forum. In short, I made this post 'cause I was curious to understand why the code behaves like this. Btw, thx for your response, I appreciate that!
var types :Array[Node]= [MyClass.new(), Node.new()]
func _ready():
for t in types:
var s = t.get_script()
if s == null:
s = t.get_class()
match s:
MyClass:
print("Myclass")
"Node":
print("node")
_:
print("idk ", s)
#output
Myclass
node
Also i;m kind of confused how your are overriding the function when you technically shouldn’t
Line 5:The method "get_class()" overrides a method from native class "Object". This won't be called by the engine and may not work as expected. (Warning treated as error.)
ah, But i guess i see you ignore that warning
The reason behind this is because of performance reasons. Native class functions do not have a virtual declaration and technically cant be overridden.
But when I do it it works
#main.gd
extends Node3D
class MyClass extends Node:
var p = ""
@warning_ignore("native_method_override")
func get_class():
return "MyClass"
pass
class TestChild extends MyClass:
@warning_ignore("native_method_override")
func get_class():
return "TestChild"
var types :Array[Node]= [MyClass.new(), Node.new(), TestNode.create(), TestChild.new()]
func _ready():
for t in types:
add_child(t)
var c = get_child(-1)
var s = c.get_class()
#if s == null:
#s = c.get_class()
match s:
"MyClass":
print("Myclass")
"Node":
print("node")
"TestNode":
print("TestNode")
_:
print("idk ", t)
#testnode.gd
extends Node
class_name TestNode
static func create():
return load("res://testnode.tscn").instantiate()
@warning_ignore("native_method_override")
func get_class():
return "TestNode"
# output
Myclass
node
TestNode
TestChild
My guess is that the gdscript function is shadowing the native class function, and is not actually overriding.
That’s interesting. So, if I get my node directly and call get_class(), like this:
print(get_child(-1).get_class()
the get_class() function will be shadowed, not overridden, and if I put it in a variable first, like this:
var a = get_child(-1)
print(a.get_class())
the get_class() will be “overridden”? That’s some good information to write down.
Also can you explain me what is a “virtual” declaration and why does that impact performance? Thx a lot for your response, it’s was very useful!
So virtual declarations are callbacks that run automatically when override them, and you just decides what it’s gonna happen inside that? If so, that’s a concept of polymorphism, wich is something I gotta study again, 'cause I don’t remember a thing about that . Anyway, thank you for your response, I apprecciate that!
There is hidden control flow when it comes to get/set property. When you define a property you automatically get functions to set and get.
var foo
...
self.set_foo("a sting")
print(self.get_foo())
print(self.foo)
# output
a string
a string
There is some strange things happening under the hood that supports this property functionality. I wonder if get_class() has some aspects of this hidden control happening that in this case can allow it to work when making a pure gdscript override.
But I would definitely heed the warning in general. Because some internal c++ functions for a class may call the native version only because it will not know that the override exists in gdscript side. (Because of the virtual function mechanics of of c++ and the binding to Gdscript)
In this case I don’t think native c++ code utilizes the get_class() function internally at all and uses different c++ mechanisms to do something similar.
I’m not sure how get_class didn’t work in your example, I tried to replicate it but did not succeed.
Yeah, this was some strange behaviour that happened. I just put my object in a variable and bum, it worked like magic. And about the warning, knowing that it works differently depending on how I call it, I think I shouldn’t have any problems, because I can call it in the way that fits better in my code. As you mention, the get_class() is probably working “under the hood” like the setters/getters, but if you said you couldn’t replicate my problem, probably it’s my code. I’m gonna be working on my project. If I found out why this happens only to my code, I’ll let u know. Anyway, thx for the help and the explanation!