I need to be able to access the class script from inside a static method, in order to support multiple constructors for my classes. I need this very badly, otherwise I am gonna have to rewrite most of my application. What I am looking for is something similar to the python @classmethod, where the class gets passed as an argument allowing you to return an instance of it. Unfortunately, there seems to be no way to access the class script from inside a static method in godot. What could be other solutions?
Emulate the behaviour of class methods (from python) in gdscript
Can you be more specific about what you are trying to do? Is this for a factory type of class?
- Edited
When I need multiple constructors, I usually just pass different arguments. Sometimes I pass a dictionary and parse out what the _init() method needs. It sounds like you're trying to do it the hard way.
So, I think you might be right, @duane . It seems the OP wants this:
var obj = Factory.create(MyClass)
Which is don't believe is possible, but let me check. However, if you already know the class name, you can do this, which is less code and more clear:
var obj = MyClass.new()
- Edited
cybereality What I need is to be able to implement one or more static methods in a class that return a class instance itself. For example:
extends Reference
class_name MyClass
var x: float = 0
func _init(x_val):
x = x_val
static func from_sum(a, b) -> MyClass:
return MyClass.new(a+b)
static func from_product(a, b) -> MyClass:
return MyClass.new(a*b)
This way I should be able to use MyClass.from_sum and MyClass.from_product as two different initializers. This code doesn't work in godot, because I am referencing MyClass from within its script, and the compiler gets mad (Although there is no actual reason for it)
As far as I can tell, you can't use the same class name inside the class itself. It's a cyclic reference in GDScript.
- Edited
You're thinking in terms of compiled languages. Gdscript isn't designed to work like that. This is the most appropriate way to do it:
extends Reference
class_name MyClass
enum {
MY_CLASS_FROM_X,
MY_CLASS_FROM_SUM,
MY_CLASS_FROM_PRODUCT,
}
var x: float = 0
func _init(how:int, val1, val2=null):
if how == MY_CLASS_FROM_SUM:
x = val1 + val2
elif how == MY_CLASS_FROM_PRODUCT:
x = val1 * val2
else:
x = val1
# main.gd
extends Node2D
func _ready():
var m = MyClass.new(MyClass.MY_CLASS_FROM_X, 10)
print(m.x)
m = MyClass.new(MyClass.MY_CLASS_FROM_SUM, 10, 5)
print(m.x)
m = MyClass.new(MyClass.MY_CLASS_FROM_PRODUCT, 10, 5)
print(m.x)
pass
Maybe you should try C# instead.
- Best Answerset by pigna
Instead of a single class, you can move the static functions into a second class. That way the cyclic dependency doesn't happen on the MyClass.new() because it's technically not in MyClass.
For example:
File 1:
extends Reference
class_name MyClass
var x: float = 0
func _init(x_val):
x = x_val
File 2:
extends Reference
class_name MyClassFrom
static func sum(a,b):
return MyClass.new(a+b)
static func product(a,b):
return MyClass.new(a*b)
File 3:
extends Node2D
func _process(delta):
var a = MyClassFrom.product(2,3)
print(a.x)
- Edited
If you don't mind it being a little hacky, you can put the generator in the same class. Note that you have to use an existing object to make the rest of the objects -- the reference doesn't exist until it's instantiated.
extends Reference
class_name MyClass
var x: float = 0
var ref = get_script()
func _new(i:float):
var n = ref.new()
n.x = i
return n
func from_sum(i:float, j:float):
var n = ref.new()
n.x = i + j
return n
func from_product(i:float, j:float):
var n = ref.new()
n.x = i * j
return n
extends Node2D
func _ready():
var my_class_generator = MyClass.new()
var m = my_class_generator._new(10)
print(m.x)
m = my_class_generator.from_sum(10, 5)
print(m.x)
m = my_class_generator.from_product(10, 5)
print(m.x)
pass
Or even...
extends Node2D
func _ready():
var m1 = MyClass.new()._new(10)
var m2 = MyClass.new().from_sum(10, 5)
var m3 = MyClass.new().from_product(10, 5)
print(m1.x)
print(m2.x)
print(m3.x)
pass
@Kojack solution is better, because it uses static functions. Otherwise you need to create a new generator object every time you need another object, which is unneeded overheard. Plus, if you are already calling new(), you might was well call new() on the object you want.