Difference between revisions of "Classes in Gideros"

From GiderosMobile
(Created page with "The Ultimate Guide to Gideros Studio __TOC__ == Classes in Gideros == Lua does not support classes the way languages like C++, Java or ActionScript do. Lua is a multi-para...")
 
 
(8 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
The Ultimate Guide to Gideros Studio
 
The Ultimate Guide to Gideros Studio
  
__TOC__  
+
__TOC__
  
 
== Classes in Gideros ==
 
== Classes in Gideros ==
 +
Lua does not support classes the way languages like C++, Java or ActionScript do. Lua is a multi-paradigm language and inherits from prototype-based languages.
  
Lua does not support classes the way languages like C++, Java or ActionScript do. Lua is a multi-paradigm language and inherits from prototype-based languages. In Lua, each object can define its own behavior through metatables, therefore, it is possible to emulate OO programming and classes in Lua.
+
In Lua, each object can define its own behavior through metatables, therefore, it is possible to emulate OO programming and classes.
  
Note: For the detailed discussion of object-oriented programming in Lua, please refer to http://www.lua.org/pil/16.html
+
'''Note''': for a detailed discussion of object-oriented programming in Lua, please refer to http://www.lua.org/pil/16.html
  
 
Gideros follows the same paradigm in its API design. Each instance created by Gideros API is a Lua table with a metatable attached.
 
Gideros follows the same paradigm in its API design. Each instance created by Gideros API is a Lua table with a metatable attached.
  
 
== Creating instances ==
 
== Creating instances ==
 
+
Instances in Gideros are created through the '''.new''' function. Consider the following examples:
Instances in Gideros are created through the .new function. Consider the following examples:
+
<syntaxhighlight lang="lua">
 
 
<source lang="lua">
 
 
local sprite = Sprite.new()
 
local sprite = Sprite.new()
 
local texture = Texture.new("image.png")
 
local texture = Texture.new("image.png")
 
local bitmap = Bitmap.new(texture)
 
local bitmap = Bitmap.new(texture)
 
local timer = Timer.new(1000, 0)
 
local timer = Timer.new(1000, 0)
</source>
+
</syntaxhighlight>
  
 
== Inheritance ==
 
== Inheritance ==
 +
The '''Core.class''' function is used to create your own classes through inheritance (older versions of Gideros used the gideros.class function -- this function has been deprecated).
  
The Core.class function is used to create your own classes through inheritance (older versions of Gideros used the gideros.class function -- this function has been deprecated). You can inherit from Gideros API's classes e.g. EventDispatcher, Sprite, etc, or from your own classes. For example, you can create your own class that inherits from EventDispatcher class like so:
+
You can inherit from Gideros API's classes e.g. EventDispatcher, Sprite, etc, or from your own classes. For example, you can create your own class that inherits from EventDispatcher class like so:
 
+
<syntaxhighlight lang="lua">
<source lang="lua">
 
 
MyEventDispatcher = Core.class(EventDispatcher)
 
MyEventDispatcher = Core.class(EventDispatcher)
</source>
+
</syntaxhighlight>
<br/>
 
  
 
You can also create a new class by using Core.class with no arguments:
 
You can also create a new class by using Core.class with no arguments:
 
+
<syntaxhighlight lang="lua">
<source lang="lua">
 
 
MyOwnClass = Core.class()
 
MyOwnClass = Core.class()
</source>
+
</syntaxhighlight>
<br/>
 
  
 
By using Inheritance, you design and implement the visual elements of your game separately:
 
By using Inheritance, you design and implement the visual elements of your game separately:
 
+
<syntaxhighlight lang="lua">
<source lang="lua">
 
 
-- create your own start button class
 
-- create your own start button class
 
StartButton = Core.class(Sprite)
 
StartButton = Core.class(Sprite)
Line 55: Line 50:
 
-- create and add a player instance to the stage
 
-- create and add a player instance to the stage
 
stage:addChild(Player.new())
 
stage:addChild(Player.new())
</source>
+
</syntaxhighlight>
<br/>
 
  
 
When an instance is created, the init function is called first:
 
When an instance is created, the init function is called first:
 
+
<syntaxhighlight lang="lua">
<source lang="lua">
 
 
Player = Core.class(Sprite)
 
Player = Core.class(Sprite)
 
function Player:init()
 
function Player:init()
Line 69: Line 62:
 
-- after Player instance is created, init function is called
 
-- after Player instance is created, init function is called
 
local player = Player.new()
 
local player = Player.new()
</source>
+
</syntaxhighlight>
<br/>
 
  
 
Whether to use inheritance or not is related to your programming taste. It is possible to implement a whole game without creating classes. You can refer to "Jumping Ball" and "Jumping Balls" examples in Gideros Studio, to see the difference between designing your code with classes or not.
 
Whether to use inheritance or not is related to your programming taste. It is possible to implement a whole game without creating classes. You can refer to "Jumping Ball" and "Jumping Balls" examples in Gideros Studio, to see the difference between designing your code with classes or not.
Line 77: Line 69:
  
 
=== Inheriting From Classes With Constructor Arguments ===
 
=== Inheriting From Classes With Constructor Arguments ===
 
 
If you inherit from a class that takes a constructor argument, your new class has to pass in the arguments that the base class expects as its first argument. You can then pass in any additional arguments:
 
If you inherit from a class that takes a constructor argument, your new class has to pass in the arguments that the base class expects as its first argument. You can then pass in any additional arguments:
 
+
<syntaxhighlight lang="lua">
<source lang="lua">
 
 
MyBitmap = Core.class(Bitmap)
 
MyBitmap = Core.class(Bitmap)
 
function MyBitmap:init(texture, additional args)
 
function MyBitmap:init(texture, additional args)
 
....
 
....
 
end
 
end
</source>
+
</syntaxhighlight>
<br/>
 
  
 
Here's a very simple example:
 
Here's a very simple example:
 
+
<syntaxhighlight lang="lua">
<source lang="lua">
 
 
A = Core.class()
 
A = Core.class()
 
function A:init(msg1)
 
function A:init(msg1)
Line 100: Line 88:
 
end
 
end
 
B.new("hello","world")
 
B.new("hello","world")
</source>
+
</syntaxhighlight>
<br/>
 
  
 
This example produces:
 
This example produces:
<source lang="lua">
+
<syntaxhighlight lang="lua">
 
A:init(hello)
 
A:init(hello)
 
B:init(hello,world)
 
B:init(hello,world)
</source>
+
</syntaxhighlight>
  
 
=== Adding Explicit Dependencies for Inherited Classes ===
 
=== Adding Explicit Dependencies for Inherited Classes ===
 
 
You can put class definitions in different files, but if it doesn't work, it may be because the files are being loaded in the wrong order. You can specify file dependencies in the IDE. To do so, select a file, right click, then select "Code Dependencies".
 
You can put class definitions in different files, but if it doesn't work, it may be because the files are being loaded in the wrong order. You can specify file dependencies in the IDE. To do so, select a file, right click, then select "Code Dependencies".
  
Line 116: Line 102:
  
 
[[File:Dependencies.jpg]]
 
[[File:Dependencies.jpg]]
 +
 +
Gideros 2020.5 introduces file dependency by code instead of Gideros project setting:
 +
<syntaxhighlight lang="lua">
 +
--!NEEDS:your_file.lua
 +
</syntaxhighlight>
 +
See '''[[Loading Order of Lua Files]]'''.
  
 
=== Accessing Overridden Functions ===
 
=== Accessing Overridden Functions ===
 
 
If you inherit from a class and override one of its functions, you have to call the overridden function using syntax like "BaseClassName.function(self)".  Here's an example:
 
If you inherit from a class and override one of its functions, you have to call the overridden function using syntax like "BaseClassName.function(self)".  Here's an example:
 
+
<syntaxhighlight lang="lua">
<source lang="lua">
 
 
-- --------------------------------------
 
-- --------------------------------------
 
A = Core.class()
 
A = Core.class()
 
function A:init(msg1)
 
function A:init(msg1)
self.text = "I'm an A"
+
self.text = "I am an A"
 
end
 
end
 
function A:method()
 
function A:method()
Line 133: Line 123:
 
B = Core.class(A)
 
B = Core.class(A)
 
function B:init(msg1, msg2)
 
function B:init(msg1, msg2)
self.text = "I'm a B"
+
self.text = "I am a B"
 
end
 
end
 
function B:method(arg1)
 
function B:method(arg1)
Line 143: Line 133:
 
b = B.new("hello","world")
 
b = B.new("hello","world")
 
b:method()
 
b:method()
</source>
+
</syntaxhighlight>
<br/>
 
  
 
This will produce:
 
This will produce:
<source lang="lua">
+
<syntaxhighlight lang="lua">
I'm a B in B:method()
+
I am a B in B:method()
I'm a B in A:method()
+
I am a B in A:method()
</source>
+
</syntaxhighlight>
<br/>
 
  
 
If you try to use "A:method()" in "B:method()" you'll get an error about a nil value for the 'text' field. That is because you are using the "A" instance that was created in the "A = Core.class()" line (equivalent to "A.method(A)").
 
If you try to use "A:method()" in "B:method()" you'll get an error about a nil value for the 'text' field. That is because you are using the "A" instance that was created in the "A = Core.class()" line (equivalent to "A.method(A)").
  
 
If you try to use "self:method()", you'll be recursively calling "B:method()".
 
If you try to use "self:method()", you'll be recursively calling "B:method()".
 +
 +
 +
'''PREV.''': [[Introduction to Lua]]<br/>
 +
'''NEXT''': [[Scene Management]]
 +
 +
 +
{{GIDEROS IMPORTANT LINKS}}

Latest revision as of 23:14, 18 November 2023

The Ultimate Guide to Gideros Studio

Classes in Gideros

Lua does not support classes the way languages like C++, Java or ActionScript do. Lua is a multi-paradigm language and inherits from prototype-based languages.

In Lua, each object can define its own behavior through metatables, therefore, it is possible to emulate OO programming and classes.

Note: for a detailed discussion of object-oriented programming in Lua, please refer to http://www.lua.org/pil/16.html

Gideros follows the same paradigm in its API design. Each instance created by Gideros API is a Lua table with a metatable attached.

Creating instances

Instances in Gideros are created through the .new function. Consider the following examples:

local sprite = Sprite.new()
local texture = Texture.new("image.png")
local bitmap = Bitmap.new(texture)
local timer = Timer.new(1000, 0)

Inheritance

The Core.class function is used to create your own classes through inheritance (older versions of Gideros used the gideros.class function -- this function has been deprecated).

You can inherit from Gideros API's classes e.g. EventDispatcher, Sprite, etc, or from your own classes. For example, you can create your own class that inherits from EventDispatcher class like so:

MyEventDispatcher = Core.class(EventDispatcher)

You can also create a new class by using Core.class with no arguments:

MyOwnClass = Core.class()

By using Inheritance, you design and implement the visual elements of your game separately:

-- create your own start button class
StartButton = Core.class(Sprite)
-- create your own menu class
Menu = Core.class(Sprite)
-- create your own player class
Player = Core.class(Sprite)
function Player:walk()
	-- walk logic
end
function Player:jump()
	-- jump logic
end
-- create and add a player instance to the stage
stage:addChild(Player.new())

When an instance is created, the init function is called first:

Player = Core.class(Sprite)
function Player:init()
   -- do the initialization of Player instance
   self.health = 100
   self.speed = 3
end
-- after Player instance is created, init function is called
local player = Player.new()

Whether to use inheritance or not is related to your programming taste. It is possible to implement a whole game without creating classes. You can refer to "Jumping Ball" and "Jumping Balls" examples in Gideros Studio, to see the difference between designing your code with classes or not.

Using classes makes it easier to reuse code.

Inheriting From Classes With Constructor Arguments

If you inherit from a class that takes a constructor argument, your new class has to pass in the arguments that the base class expects as its first argument. You can then pass in any additional arguments:

MyBitmap = Core.class(Bitmap)
function MyBitmap:init(texture, additional args)
	....
end

Here's a very simple example:

A = Core.class()
function A:init(msg1)
	print("A:init("..msg1..")")
end
B = Core.class(A)
function B:init(msg1, msg2)
	print("B:init("..msg1..","..msg2..")")
end
B.new("hello","world")

This example produces:

A:init(hello)
B:init(hello,world)

Adding Explicit Dependencies for Inherited Classes

You can put class definitions in different files, but if it doesn't work, it may be because the files are being loaded in the wrong order. You can specify file dependencies in the IDE. To do so, select a file, right click, then select "Code Dependencies".

For example, if class A (in classA.lua) inherits from class B (in classB.lua) and you're getting a message like "attempt to index global 'B' (a nil value)" during the initialization process, select "classA.lua" and add a dependency on classB.lua.

Dependencies.jpg

Gideros 2020.5 introduces file dependency by code instead of Gideros project setting:

--!NEEDS:your_file.lua

See Loading Order of Lua Files.

Accessing Overridden Functions

If you inherit from a class and override one of its functions, you have to call the overridden function using syntax like "BaseClassName.function(self)". Here's an example:

-- --------------------------------------
A = Core.class()
function A:init(msg1)
	self.text = "I am an A"
end
function A:method()
	print(self.text .. " in A:method()")
end
-- --------------------------------------
B = Core.class(A)
function B:init(msg1, msg2)
	self.text = "I am a B"
end
function B:method(arg1)
	print(self.text .. " in B:method()")
	--A:method()       <--- NOT THIS
	A.method(self)   
end
-- --------------------------------------
b = B.new("hello","world")
b:method()

This will produce:

I am a B in B:method()
I am a B in A:method()

If you try to use "A:method()" in "B:method()" you'll get an error about a nil value for the 'text' field. That is because you are using the "A" instance that was created in the "A = Core.class()" line (equivalent to "A.method(A)").

If you try to use "self:method()", you'll be recursively calling "B:method()".


PREV.: Introduction to Lua
NEXT: Scene Management