Page 1 of 1

extends Array

Posted: 27 Sep 2019, 04:03
by bourdin07
How to extends the native Array ?

I tried :

Code: Select all

class _Array
{
	test()
	{
		return "ok"
	}
}

Array.base := _Array

msgbox(Array.test()) ; doesn't work
Also I can't do that why ?

Code: Select all

class Array extends _Array
{
}
"Duplicate Array Declaration"

Re: extends Array

Posted: 28 Sep 2019, 07:42
by lexikos
What are you trying to do?

You can define a class which extends Array, as in class CustomArray extends Array, which you instantiate with new CustomArray(). You cannot redefine or "reopen" a class.

If you want to change all arrays, everywhere, you can do that my modifying Array.prototype with direct method calls and assignments. Whether you should is another matter.

Your test() method is an instance method. You must instantiate the class to call an instance method.

Changing the base of an existing class only affects inheritance of static methods and properties. Array instances are derived from Array.Prototype, which is still based on Object.Prototype.

Re: extends Array

Posted: 28 Sep 2019, 08:53
by lvalkov
I believe the goal is to circumvent the laborious process of (mostly) manually defining Array extension methods, according to the template:

Code: Select all

Array.Prototype.DefineMethod('extensionMethod', this => (/* implementation details */))
by defining a class instead, having it extend Array (so as to inherit Array's already existing methods and properties) and finally replacing the default Array class with their own one. For instance:

Code: Select all

class Default {
	defaultMethod() => ''
}

class Extension extends Default {
	extensionMethod() => ''
}

Default.Prototype := Extension.Prototype

D := new Default()
MsgBox D.__Class ; Extension
MsgBox D.HasMethod('defaultMethod') ; true 
MsgBox D.HasMethod('extensionMethod') ; true
Applying the same exact recipe to Array necessitates additionally overriding the Array() / [] function/operator:

Code: Select all

class Extension extends Array {
	extensionMethod() => ''
}

Array.Prototype := Extension.Prototype
Array(Args*) => Array.New(Args*)

A := []
MsgBox A.__Class ; Array
MsgBox A.HasMethod('Pop') ; true
MsgBox A.HasMethod('extensionMethod') ; true

Re: extends Array

Posted: 28 Sep 2019, 17:50
by lexikos
So what happens if a user wants to use your Array library with another Array library?

The user must modify one of the libraries to remove the duplicate Array function, and merge one extension class into the other.

As I said, you can do it by modifying Array.prototype with direct method calls and assignments. By direct, I only mean that the call targets the prototype object. The unnecessary laborious part is repeating Array.prototype.DefineMethod(...) for each method (and Extension.prototype.GetMethod(...) or Func(...) if you do not use fat arrow functions). Why repeat yourself?

Code: Select all

class Extension extends Array {
	extensionMethod() => ''
	extensionProp => 42
}

ExtendDef(obj, ext) {
	for name, method in ext.OwnMethods()
		obj.DefineMethod(name, method)
	for name in ext.OwnProps()
		if desc := ext.GetOwnPropDesc(name)
			obj.DefineProp(name, desc)
}

Class.Prototype.DefineMethod("ExtendDef", (this, ext) => (
	ExtendDef(this.Prototype, ext.Prototype)
))

Array.ExtendDef(Extension)

A := []
MsgBox A.__Class ; Array
MsgBox A.HasMethod('Pop') ; true
MsgBox A.HasMethod('extensionMethod') ; true
MsgBox A.extensionProp ; 42
Developing shared libraries/contentions such as ExtendDef can be a community effort. Alternatively, you can just use a couple of lines:

Code: Select all

for name, method in Extension.Prototype.OwnMethods()
    Array.Prototype.DefineMethod(name, method)
MsgBox A.__Class ; Array
Yours shows Extension, not Array.