Use Classes as dictionary keys

Godot Version

4.2

Question

I’m trying to use Classes as dictionary keys so I could do somthing like the following:

    var handlers = {}

    func registerHandler(handler):
        handlers[handler.get_class()] = handler

Unfortunately the get_class method always returns the name of the native class.

So I found that there is a get_script method and when you print a class you actually get the ID or str of this Script, whatever it is. So if my class was the following.

    class_name Handler

then I could use the get_script in a dictionary to look it up:

    var handler = Handler.new()
    print(handler.get_script() == Handler)  # is true

    handlers[handler.get_script()] = handler

But I’m not sure, if I’m supposed to use it like this. I don’t exactly know what this Script is. Is it unique? I dont know how classes work in GDScript in general and atm I’m contemplating switching to C#, because it seems GDScript is missing a lot of features. Can anybody shed some light on this or refer me to a webpage where I can read up on this topic?

Or just tell me how I’m supposed to do this in GDScript.

I don’t understand why you want to use a class as an key (essentially an index) to an element in a dictionary.
Is there some reason you can’t just use a text name?
get_script() returns an object.
By the way, this issue would be the exact same in C# …or at least my confusion on what you are trying to accomplish would be the same.
To my way of thinking trying to use a class as a key is the same as trying to use a type specifier as a key.
Maybe there is an argument to be made that you want to use an instance of a class as a key but more likely you want a string value.

Again… the string that get_class returns is always the native class. So Resource or Object. If I have multiple custom Resources I wouldn’t be able to know which is which at runtime.

Since tuples are not a thing in GDScript either I’d have to pass around an untyped Array with the String and the object. There has to be a better solution. The most obvious is to ask the instance what its class is.

That is a very basic thing in other programming languages. I dont know much about C#, but I would have expected this to work in C#.

I’m still really not following you here.
get_class isn’t reliable because it returns the base class name as a string. But even if it gave up the derived class name it is still a string.
You can add a function to return the derived class name:

func get_real_class_name()->String: 
    return "MyClass"

You end up with a string name of the class.

By the way supposedly the derived class name is available via get_global_name() however it must be implemented in a more recent build as I can’t find it in my 4.2 stable version.

1 Like

Well yes…

I read about that too in the github issue that I posted. People overriding get_class as a work around. But, since it’s an older issue, I was hoping for a better solution. It also doesn’t work when I don’t have an Instance at hand. Hardcoding a String into the code seems like bad practice to me, while using the Class would make my intention also more obvious. I guess I could create a static function as a workaround. I dont think static const is a thing? I still don’t like it though. That’s a lot of classes with unnecessary code.

get_global_name was also mentioned as a possible solution, but it seems the commit you mentioned is bleeding edge and only part of the master branch.