Jump to content


Dynamic class creation


  • Please log in to reply
14 replies to this topic

#1 nfl

nfl
  • Guests

Posted 19 October 2011 - 12:21 PM

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

#2 fragman

fragman
  • Members
  • 1591 posts

Posted 19 October 2011 - 03:22 PM

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.

#3 HotKeyIt

HotKeyIt
  • Fellows
  • 6132 posts

Posted 19 October 2011 - 07:59 PM

It seems to work if you remove the parenthesis :?
v%A_Index% := new Test_%A_Index% ;()


#4 nfl

nfl
  • Guests

Posted 19 October 2011 - 09:47 PM

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 :)

#5 Lexikos

Lexikos
  • Administrators
  • 8844 posts

Posted 20 October 2011 - 12:56 AM

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.

#6 jaco0646

jaco0646
  • Fellows
  • 3163 posts

Posted 20 October 2011 - 01:16 AM

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.

#7 nimda

nimda
  • Members
  • 4301 posts

Posted 20 October 2011 - 01:35 AM

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.

#8 Lexikos

Lexikos
  • Administrators
  • 8844 posts

Posted 20 October 2011 - 02:26 AM

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.

#9 jaco0646

jaco0646
  • Fellows
  • 3163 posts

Posted 20 October 2011 - 02:50 AM

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.

#10 Lexikos

Lexikos
  • Administrators
  • 8844 posts

Posted 20 October 2011 - 03:58 AM

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.

#11 nfl

nfl
  • Guests

Posted 21 October 2011 - 08:59 AM

You could always use a temporary variable:

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

Thanks, that works :)

#12 fragman

fragman
  • Members
  • 1591 posts

Posted 21 October 2011 - 10:59 AM

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.

#13 Lexikos

Lexikos
  • Administrators
  • 8844 posts

Posted 21 November 2011 - 01:00 AM

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.

#14 Guest Today

Guest Today
  • Guests

Posted 01 December 2011 - 03:28 PM

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?

#15 Guests

  • Guests

Posted 15 December 2011 - 03:20 AM

Try this:
F(ErrorLevel) {
    ;...
}
or this:
F() {
    local ErrorLevel
}