[a130] unexpected class.__Init behavior Topic is solved

Report problems with documented functionality
User avatar
aseiot
Posts: 79
Joined: 05 Mar 2017, 04:25

[a130] unexpected class.__Init behavior

Post by aseiot » 04 Apr 2021, 06:39

With the latest a130, I encounter a unexpected problem when define multiple subclass (in separate scripts) derivate from same base class.
Following code demonstrate the issue:

bs.ahk

Code: Select all

class bs
{
	something := 1			; Must with some InstanceVar, to trigger bs.__Init()?
}

A.ahk

Code: Select all

class A extends bs
{
	A := "A"				; unexpected called by bs.__Init()
}


#Include bs.ahk

B.ahk

Code: Select all

class B extends bs
{
	B := "B"
}


X := B()
MsgBox X.A X.B				; suppose error, but actually get "AB"


#Include bs.ahk
#Include A.ahk
If the A and B subclasses are in a same file, the issue is gone.

Code: Select all

class A extends bs
{
	A := "A"
}

class B extends bs
{
	B := "B"
}


X := B()
MsgBox X.A X.B					;Error:  This value of type "B" has no property named "A".


#Include bs.ahk

lexikos
Posts: 9494
Joined: 30 Sep 2013, 04:07
Contact:

Re: [a130] unexpected class.__Init behavior

Post by lexikos » 06 Apr 2021, 03:39

Thanks.

It is not due to using separate files or having multiple subclasses.

The issue is that initializers are added to an inherited __Init method if one exists, instead of defining a new one. This is of course unintended and will be fixed.

In other words,

Code: Select all

MsgBox bs().subProp ; 3
class bs {
    baseProp1 := 1 ; HasMethod(bs.Prototype, "__Init") = false, so __Init is defined
    baseProp2 := 2 ; this line is added to GetMethod(bs.Prototype, "__Init")
}
class sub extends bs {
    subProp := 3 ; this line is added to GetMethod(sub.Prototype, "__Init")
}
When you combined A and B into one file, you changed the order that the classes are defined in, putting them before the base class. This is hard to see in your post, because of the order you write the files and the multiple #Include directives.

You can replicate what the parser should be doing like this:

Code: Select all

MsgBox bs().subProp ; error
class bs {
    baseProp1 := 1, baseProp2 := 2
}
class sub extends bs {
    __Init() {
        super.__Init()
        ;<instance var initializers are inserted here>
    }
    subProp := 3 ; sub has __Init (inherited), so this line is added to it
}
But according to the current documentation, "a single class definition must not contain both an __Init method and an instance variable declaration". What's left unsaid is "(because otherwise, you'll either get a duplicate declaration error or the initializers will be dumbly inserted at the end of the function, which may cause confusion and not necessarily allow the initializers to be evaluated; this should not be relied upon as it may change)".

If you define __Init explicitly and put the initializer into it yourself, you are compliant with the current documentation.

User avatar
aseiot
Posts: 79
Joined: 05 Mar 2017, 04:25

Re: [a130] unexpected class.__Init behavior

Post by aseiot » 06 Apr 2021, 08:17

Thanks for the explanation! :)

lexikos
Posts: 9494
Joined: 30 Sep 2013, 04:07
Contact:

Re: [a130] unexpected class.__Init behavior  Topic is solved

Post by lexikos » 20 Apr 2021, 04:52

Fixed by v2.0-a131.

Post Reply

Return to “Bug Reports”