Page 1 of 1

[v2 - a108][Tips] How to create a Class property for instances of a class.

Posted: 29 Apr 2020, 09:03
by Helgef
TLDR

Prerequisites.
:arrow: Classes and :arrow: static __new.

Introduction and examples.
Sometimes we want to refer to a static method or property when we use an instance of a class. We can do this by directly referring to the class through its super global variable. This implies a few problems, we need to hard-code class names and and we need to consider variable scope. Example,

Code: Select all

class x {
	static prop := 'A'
	g() {
		msgbox x.prop
	}
}
instance_of_x := x.new()
instance_of_x.g ; A
Here we refer to x directly, x is hard-coded and we need to declare it in g() if we force local. Now, consider the case where a class y extends x, and we want y to define its own prop property, and display it in the method g(),

Code: Select all

class y extends x {
	static prop := 'B'
}
How to write g() now? We could do like this,

Code: Select all

g() {
	if this is x
		msgbox x.prop
	else if this is y
		msgbox y.prop
}
This would work but is obviously not very maintainable and quickly becomes worse if more static properties and methods or sub-classes are to be considered. A better solution would be something like this,

Code: Select all

g() {
	msgbox this.Class.prop
}
where this.Class returns the class of the instance this, in the example that would be either x or y.

How to setup a Class property for instances of a class.
Simply add one line to the super class' static __new method,

Code: Select all

static __new() => this.prototype.Class := this
Exmaple,

Code: Select all

class x {
	static __new() => this.prototype.Class := this
	static prop := 'A'
	g() {
		msgbox this.Class.prop
	}
}
class y extends x {
	static prop := 'B'
}
instance_of_x := x.new()
instance_of_y := y.new()
instance_of_x.g ; A
instance_of_y.g ; B
Obviously this creates a circular reference for the class objects, but I consider this harmless. But be aware if you have special needs. Also, if a sub-class defines its own static __new method you need to either call base.__new() or repeat the assignment.

Exercises.
1) Explain some of the limitation and issues with using %this.__class% vs. the proposed this.Class property. Hint, some have already been mentioned above.

2) Create a Class property which takes one integer parameter to access super-classes, i.e., complete the code below,

Code: Select all

class x {
}
class y extends x {
}
class z extends y {
}

instance_of_z := z.new()

msgbox instance_of_z.class == z		; 1
msgbox instance_of_z.class[1] == y  ; 1
msgbox instance_of_z.class[2] == x  ; 1
Please use spoiler-tags if you post solutions to the exercises.

Cheers.

Re: [v2 - a108][Tips] How to create a Class property for instances of a class.

Posted: 29 Apr 2020, 09:24
by swagfag
u can already do that with

Code: Select all

msgbox %this.__Class%.prop

Re: [v2 - a108][Tips] How to create a Class property for instances of a class.

Posted: 29 Apr 2020, 11:28
by Helgef
Thanks @swagfag, I'd forgot about that, I've updated my post above ;).

Cheers.