Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate

Dynamic class creation


  • Please log in to reply
15 replies to this topic
nfl
  • Guests
  • Last active:
  • Joined: --
Hi,
instances of classes can't be created dynamically:
v0 := new Test()
Loop, 2
	v%A_Index% := new Test_%A_Index%()
msgbox % v0.var1 . " - " . v0.var2 . "`n" . v1.var1 . " - " . v1.var2 . "`n" . v2.var1 . " - " . v2.var2
Loop, 2 {
	if (A_Index = 1)
		v%A_Index% := new Test_1()
	if (A_Index = 2)
		v%A_Index% := new Test_2()
}
msgbox % v0.var1 . " - " . v0.var2 . "`n" . v1.var1 . " - " . v1.var2 . "`n" . v2.var1 . " - " . v2.var2

class Test {
	var1 := "bla"
	var2 := "tra"
}

class Test_1 extends Test {
	var2 := "ho"
}

class Test_2 extends Test_1 {
	var1 := "bli"
}
Is this intended behavior?

Regards, nfl

fragman
  • Members
  • 1591 posts
  • Last active: Nov 12 2012 08:51 PM
  • Joined: 13 Oct 2009
I think this was discussed before. If you have an instance of a class, you can easily create a new instance with it. You could maybe also try to create an object like this:
NewInstance := new {base : { __Class : "InstanceNameYouWantToCreate"}}
. No idea if it works though or if AHK_L looks at other keys than the __Class key.

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
It seems to work if you remove the parenthesis :?
v%A_Index% := new Test_%A_Index% ;()


nfl
  • Guests
  • Last active:
  • Joined: --

NewInstance := new {base : { __Class : "InstanceNameYouWantToCreate"}}

Doesn't work. It won't run with the "new" keyword, but without it, the class isn't created, just the object with a base that includes the __Class key.

@HotKeyIt:
This works, though :O I'll use this for now, maybe Lexikos can clarify what's going on here :)

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
I'm aware of the limitation. Since new is also a valid variable name, it is treated as an operator only if followed by something that looks like a class name (even though the class name is ultimately parsed as an expression). This probably isn't documented; I'll do something about that when I get time. On the other hand, changing it to interpret new as an operator whenever it is followed by something that isn't an operator might be feasible.

You could always use a temporary variable:
v := Test_%A_Index%, v%A_Index% := new v()

NewInstance := new {base : { __Class : "InstanceNameYouWantToCreate"}}

There's probably no good reason to use both new and base: that way. It should either be new {__Class: "..."} (which currently doesn't work) or {base: {__Class: "..."}}. However, I think that's not really relevant to the topic of this thread, which seems to be instantiating a pre-defined class via a dynamic variable.

jaco0646
  • Moderators
  • 3165 posts
  • Last active: Apr 01 2014 01:46 AM
  • Joined: 07 Oct 2006

Since new is also a valid variable name,

I think it would make sense to introduce the concept of reserved words to AHK at some point. The question of where to document true and false came up recently, as well as the issue of reserving between, is, in, and contains as expression operators. Then there are and, or, not, plus likely others I'm not thinking of right now. EDIT2: Perhaps ErrorLevel should be reserved?

EDIT: the main section on variable names seems like a good place to list these exceptions; but they should be formally reserved rather than just discouraged.

nimda
  • Members
  • 4368 posts
  • Last active: Aug 09 2015 02:36 AM
  • Joined: 26 Dec 2010
i=i

%i%f=if

not%_%=not

If (if == "if")

   MsgBox % not%_%

ListVars

WinWaitClose % A_ScriptFullPath
this is really strange behavior which can lead to weird bugs. I agree with jaco0646.

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
FYI, when I initially implemented new as an operator, the very first real world script I ran failed, because I had used "old" and "new" as variable names. I then changed the implementation, with the intention of reserving "new" as an operator in v2.0.

... reserving between, is, in, and contains as expression operators.

I won't be implementing between..and as an operator, so it will not be reserved. As with and/or/not, is/in/contains/new won't be disallowed as variable names (for code size and performance reasons), but they will be interpreted as operators when appropriate. I see little value in specifically disallowing those variable names. (However, documenting them as reserved is a different matter.)

EDIT2: Perhaps ErrorLevel should be reserved?

I don't quite get your meaning. It's essentially already reserved, as are all names of built-in variables.

this (...) can lead to weird bugs.

How? It's perfectly legitimate to write:
if = foo
MsgBox % if
... without any ambiguity, but who would actually do it? It has to be supported for commands like "Control" or "Input", which are more likely to be used as variable names.

I think it would make sense to introduce the concept of reserved words to AHK at some point.

I don't disagree, but it's unlikely I'll do anything about it myself any time soon.

jaco0646
  • Moderators
  • 3165 posts
  • Last active: Apr 01 2014 01:46 AM
  • Joined: 07 Oct 2006
By reserved, I meant disallowed as an output variable.

performance reasons

Does that mean the current (bloated) list of constants is hurting performance? We could definitely trim that down if it would help.

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006

By reserved, I meant disallowed as an output variable.

Why?

Does that mean the current (bloated) list of constants is hurting performance?

Any time a new variable is (about to be) created, the name is checked against the names of built-in variables. In most cases this only involves checks against a few names (including "true" and "false") and the "A_" prefix. In retrospect, performance of variable creation isn't generally an issue in real-world scripts. The bigger issue is that I don't see the benefit to your suggestion, so couldn't justify spending my time on it.

nfl
  • Guests
  • Last active:
  • Joined: --

You could always use a temporary variable:

v := Test_%A_Index%, v%A_Index% := new v()

Thanks, that works :)

fragman
  • Members
  • 1591 posts
  • Last active: Nov 12 2012 08:51 PM
  • Joined: 13 Oct 2009
That's actually what I'm using now as well. My classes register themselves at a master class by employing the early assignment of static properties.

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
v1.1.05.02 has been released.

Fixed new %VarContainingClassName%().

I had actually allowed for double-derefs, but the code for dynamic function calling was interfering. Note that new %Var% (without parentheses) and new %Var%.NestedClass() already worked.

Guest Today
  • Guests
  • Last active:
  • Joined: --

jaco0646 Wrote:
EDIT2: Perhaps ErrorLevel should be reserved?

Lexikos Wrote:
I don't quite get your meaning. It's essentially already reserved, as are all names of built-in variables.


I don't understand "essentially already reserved"

The following are treated as valid variables.
errorlevel := "JellyBean" ;this is allowed

input := "JellyBean" ;this is allowed

control := "JellyBean" ;this is allowed

How are they reserved?

  • Guests
  • Last active:
  • Joined: --
Try this:
F(ErrorLevel) {
    ;...
}
or this:
F() {
    local ErrorLevel
}