Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Class definition syntax for AutoHotkey


  • Please log in to reply
96 replies to this topic
Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
v2.0-a010 contains the following changes merged from the v1 branch:
[*:u5did9hf]Implemented class variables.
[*:u5did9hf]Changed __New and __Delete to not trigger base.__Call.
[*:u5did9hf]Changed base.Method() and base.Property to not trigger meta-functions.
[*:u5did9hf]Fixed x.y++ and x.y-- unrecognized when alone on a line.
[*:u5did9hf]Fixed new "quoted string" to be interpreted as auto-concat rather than new op. Most of this is mentioned in my previous post.

Class variable declarations are handled similarly to static var initializers:
ListLines
Pause
class C {
    var x := 1, y := 2
}
004: C.x := 1, C.y := 2  
001: ListLines


tonne
  • Members
  • 1654 posts
  • Last active: May 06 2014 06:22 PM
  • Joined: 06 Jun 2006
I'm trying to create an instance of classb in classa.__new, but to no avail.
Is it even possible?
a := new classa()
return

class classb
{
  __new()
  {
    msgbox "new classb" ; this is never reached
  } 
}

class classa
{
  var _b
  __new()
  {
    msgbox "new classa" ;
    this._b := new classb()
  }
}


a4u
  • Guests
  • Last active:
  • Joined: --
Thanks for the updates :)

@tonne - see this post. Currently, classb would need to be global to access it in the classa.__new method.

tonne
  • Members
  • 1654 posts
  • Last active: May 06 2014 06:22 PM
  • Joined: 06 Jun 2006
Thank you; works nicely.

a4u
  • Guests
  • Last active:
  • Joined: --
Just a thought, but to avoid confusion, it might possibly be better to use the keyword prototype rather than class.

IsNull
  • Moderators
  • 990 posts
  • Last active: May 15 2014 11:56 AM
  • Joined: 10 May 2007

Just a thought, but to avoid confusion, it might possibly be better to use the keyword prototype rather than class.

Now we have class syntax and you want it call prototype? Somewhat beyond my understanding :mrgreen:

Seriously, I think I get your point: Because it's still possible to "extend" class instances the prototype way might be your reason- but this ability doesn't make the defintion an "prototype" IMHO.

a4u
  • Guests
  • Last active:
  • Joined: --

... but this ability doesn't make the defintion an "prototype" IMHO.

True - but the definition is a prototype regardless.

Lexikos[/url]":12yb2a4q]It's convenient to say "class definition", but it's actually a prototype definition, and is purely syntax sugar.

class C {
	var key := "value"
	__New() {
		; this.base := this.base.Clone()
	}
}

for k,v in C
	t .= "%k`t= %v`t(" Type(v) ")`n"
MsgBox, , % "var C type = " Type(C), %t%

a := new C, b := new C
b.base.key := "modified base key"
MsgBox, % a.key "`n" b.key
C.key :=  "modified prototype key"
MsgBox, % a.key "`n" b.key

Prototype-based programming is a style of object-oriented programming in which classes are not present ...

In object-oriented programming, a class is a construct that is used as a blueprint to create instances of the class ...

Don't get me wrong, I'm not against using the keyword class, I just think it may cause confusion since it's actually a prototype.

guest3456
  • Members
  • 1704 posts
  • Last active: Nov 19 2015 11:58 AM
  • Joined: 10 Mar 2011
thanks a4u

first, i get call to non existent function Type(). i'm not exactly sure what youre trying to show with the for loop

second, what does base refer to in the constructor? i am thinking that b.base refers to the class C. but what does this.base refer to in class C, since C doesn't extend any other class?

but i think i understand the difference between prototype and class based oop now, based on your example. so if i uncomment out your constructor, then this object would behave like a normal "class based" oop class. but if we leave the constructor commented, then it behaves like a prototype, which can be modified on the fly and all instances get updated as well. is this right?

if so, i think this would be a great example to include in the docs to describe the differences with prototype based oop

guest3456
  • Members
  • 1704 posts
  • Last active: Nov 19 2015 11:58 AM
  • Joined: 10 Mar 2011

My idea in its current form:

class Foo extends Bar
{
    ; This is explicitly a declaration, not to be confused with a line
    ; of code to be executed.  Store 0 in Foo["Flavour"].  
    var Flavour := 0
    
}


can someone explain the comment above to me? what is the difference between a line of code to be executed and the above var keyword ? i guess i'm asking, why couldn't the var keyword be left out there?

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
This is similar to static in functions, that line (var ...) will only execute once when script is launched.

Type() function only exist in AHK v2 :!:

IsNull
  • Moderators
  • 990 posts
  • Last active: May 15 2014 11:56 AM
  • Joined: 10 May 2007
Is it possible to traverse the inheritance tree in 1.1?

How can this be rewritten, to check if a derived class bases on a specific type, without modify the classes?

#Warn
#NoEnv

myfoo := new Foo()

[color=red]if(myfoo is Bar){
	MsgBox myfoo is an (Sub)Instance from Bar 
}[/color]


class Bar
{

}

class Foo extends Bar
{
	
}

__Class is nice, but I dont see any way to check for the base class name, as foo.base._Class logicaly returns also "Foo".

a4u
  • Guests
  • Last active:
  • Joined: --

what does base refer to in the constructor? i am thinking that b.base refers to the class C. but what does this.base refer to in class C, since C doesn't extend any other class?

In the constructor, this refers to the object being created. So, this.base refers to the class C - which is the prototype object.

... I dont see any way to check for the base class name, as foo.base._Class logicaly returns also "Foo".

For your example, the base of myfoo is Foo. The base of Foo is Bar. You could test this as such:
if(myfoo.base.base.__Class = "Bar")
Also, is there any way to byref access this? This would be useful when using the default base (here for instance), though it may be better not to use class syntax.

IsNull
  • Moderators
  • 990 posts
  • Last active: May 15 2014 11:56 AM
  • Joined: 10 May 2007

For your example, the base of myfoo is Foo. The base of Foo is Bar.

You are right. Thanks. This Class Design over Prototypes has some background diffrences which we have to care about when thinking in class Design.

I implemented "is" as following:


is(obj, type){
	while(IsObject(obj)){
		
		if(obj.__Class == type){
			return true
		}
		obj := obj.base
	}
	return false
}


Example:

myfoo := new Foo()

if(is(myfoo, "Bar")){
   MsgBox myfoo is an (Sub)Instance from Bar 
}else{
	MsgBox myfoo is NOT an (Sub)Instance from Bar
}


class Bar
{

}

class BumBum extends Bar
{
		
}

class Foo extends BumBum
{
   
}

is(obj, type){
	while(IsObject(obj)){
		
		if(obj.__Class == type){
			return true
		}
		obj := obj.base
	}
	return false
}


guest3456
  • Members
  • 1704 posts
  • Last active: Nov 19 2015 11:58 AM
  • Joined: 10 Mar 2011


My idea in its current form:

class Foo extends Bar
{
    ; This is explicitly a declaration, not to be confused with a line
    ; of code to be executed.  Store 0 in Foo["Flavour"].  
    var Flavour := 0
    
}


can someone explain the comment above to me? what is the difference between a line of code to be executed and the above var keyword ? i guess i'm asking, why couldn't the var keyword be left out there?


This is similar to static in functions, that line (var ...) will only execute once when script is launched.


but its not possible to have normal executing lines in the class definition?

something like this throws error:

class foo
{
   var myproperty := 0
   executeFuncOutsideClass()
}

return  ;// end of autoexec

executeFuncOutsideClass()
{
  msgbox, hello world
}

or am i just overcomplicating everything and not understanding?

EDIT/
ohhh i see, its saying that you MUST use 'var' keyword to define class variables, you cannot just use "key := value" because that is a normal executing line. i got it. thanks

Frankie
  • Members
  • 2930 posts
  • Last active: Feb 05 2015 02:49 PM
  • Joined: 02 Nov 2008
How does that work exactly? You can either use var to assign a value, or give a value in the constructor? Or does it have to be declared (with var) first, and then given a value in the constructor?
aboutscriptappsscripts
Request Video Tutorials Here or View Current Tutorials on YouTube
Any code ⇈ above ⇈ requires AutoHotkey_L to run