i've attached my "game". run it and check out stdout.txt to see the results (nothing "visual". it just output's some text).
a_dog's describe variable works well. i have a bit of a problem with checking to see if it can fly though. the mammal class has fly and canFly functions. canFly just returns 0, and fly prints "I've no wings, I can't fly!". i then include the hasWings module to the class and that 'overwrites' (?) the 2 functions with it's own ones (the new canFly returns 1 (true) and fly returns 'flap flap flap!'. i don't know if this is the right way to do it. the reason i have the 2 fly and canFly functions in the mammal class in the first place is because i have no other way of checking to see if it can fly or not.
secondly, what i tried to do was create a subclass for mammal called dog. dog can just be empty if i needed but it was there so that when i did local dog1 = dog:new(...) i knew i was getting a dog. i could then make other subclasses for mammal, like "bat" which would inclue "hasWings". the problem here is when i make an empty subclass "dog", and call the function describe, it doesnt exist. do i need to re-write all the functions in dog and call super(self,...)? that'd work, but it just seems like alot of re-writing for nothing.
PÄSSION ~ Mixins and subclasses questions
- TechnoCat
- Inner party member
- Posts: 1611
- Joined: Thu Jul 30, 2009 12:31 am
- Location: Milwaukee, WI
- Contact:
Re: PÄSSION ~ Mixins and subclasses questions
Nothing is attached.
Re: PÄSSION ~ Mixins and subclasses questions
sorry..
- Attachments
-
- middleclass.zip
- (2.39 KiB) Downloaded 172 times
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: PÄSSION ~ Mixins and subclasses questions
Ok, here are some comments:
You don't need to store the class name on your instances like this:
Instead, you can use the class.name:
In your case, it will print "I am a Mammal" - if you want to print "I am a Dog" you must have a Dog class - but you have the canFly() problem. Let's handle that.
The easiest way to test if a class implements a function is ... to see if that function is there!
I would change this:
To this:
Note that you will not need 'canFly' any more - it is safe to remove it from your interface and Mammal. Your Dog class now only needs an initializer that calls super.
This approach is similar to what is done in javascript libraries, for handling browser compatibility. Instead of asking "am I in IE or Firefox?" you just ask "do I have xxx function?". For your particular example, this is the easiest solution.
However, for a big interface with lots of functions it would be tiresome to test all them. In those cases you could use a solution similar to the one that you implemented. But instead of a function, you could use a boolean:
Then, in your code, you can do:
canFly will return true if the interface is implemented, and nil otherwise.
I hope this helps.
[EDIT - answered *both* questions instead of just the first]
You don't need to store the class name on your instances like this:
Code: Select all
function X:initialize()
self.name_type = name_type
end
...
print('I am a ' .. self.name_type .. '.')
Code: Select all
function X:initialize()
end
print('I am a ' .. self.class.name .. '.') --this will print "I am a X."
The easiest way to test if a class implements a function is ... to see if that function is there!
I would change this:
Code: Select all
if self:canFly() then
print('I can fly!')
self:fly()
else
print("I can't fly!");
end
Code: Select all
if type(self.fly) == "function" then
print('I can fly!')
self:fly()
else
print("I can't fly!");
end
Code: Select all
Dog = Mammal:subclass('Dog')
function Dog:initialize(name,color,sound)
super(self,name,color,sound)
end
However, for a big interface with lots of functions it would be tiresome to test all them. In those cases you could use a solution similar to the one that you implemented. But instead of a function, you could use a boolean:
Code: Select all
hasWings = {}
hasWings.canFly=true --the boolean
function hasWings.fly()
print('flap flap flap!')
end
... -- more functions on hasWings here
Code: Select all
if(self.canFly) then
... -- use lots of hasWings functions here
end
I hope this helps.
[EDIT - answered *both* questions instead of just the first]
When I write def I mean function.
Re: PÄSSION ~ Mixins and subclasses questions
Thanks kikito! very help and thorough answer. i've fixed up my script. i've also attached it to this post for anyone who is at my level and wishes to learn from it
Code: Select all
require 'MiddleClass.lua'
Animal = class('Animal')
function Animal:initialize(name,color)
self.name = name
self.color = color
end
function Animal:describe()
print('My name is ' .. self.name .. '.')
print('I am of a ' .. self.color .. ' color.')
end
hasWings = {}
function hasWings.fly()
print('flap flap flap!')
end
hasWings.canFly = true
Mammal = Animal:subclass('Mammal')
function Mammal:initialize(name,color,sound)
super(self,name,color)
self.sound = sound or nil
end
function Mammal:describe()
super(self)
print('I am a ' .. self.name_type .. '.')
if self.sound ~= nil then
print('I can speak!')
self:speak(5)
else
print("I can't speak!")
end
if self.canFly == true then
print('I can fly!');
self:fly();
else
print("I can't fly!");
end
end
function Mammal:speak(count)
count = count or 1;
if self.sound ~= nil then
repeat
print(self.sound .. '!!');
count = count - 1
until count == 0
else
print('...!!!');
end
end
--make a dog
Dog = Mammal:subclass('Dog')
function Dog:initialize(name,color,sound)
super(self,name,color,sound)
self.name_type = self.class.name
end
local dog1 = Dog:new('Billy','white','wolf')
dog1:describe()
print('----')
--make a bat
Bat = Mammal:subclass('Bat')
function Bat:initialize(name,color,sound)
super(self,name,color,sound)
self.name_type = self.class.name
end
Bat:includes(hasWings)
local bat1 = Bat:new('John','brown')
bat1:describe()
- Attachments
-
- middleclass.love
- (2.26 KiB) Downloaded 168 times
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: PÄSSION ~ Mixins and subclasses questions
Hmm your code works, but it has a weakness.
You are using self.name_type on Mammal. However, this member variable is being set by Dog and Bat, but not by Mammal. This is easy to control in your example, but is not a good practice in general; with more complicated classes you will end up forgetting to set up the variables on your subclasses.
So you should either request it as a parameter on your Mammal constructor, and set it up there, or better, just use class.name directly and ignore name_type. You would end up with something like this:
You are using self.name_type on Mammal. However, this member variable is being set by Dog and Bat, but not by Mammal. This is easy to control in your example, but is not a good practice in general; with more complicated classes you will end up forgetting to set up the variables on your subclasses.
So you should either request it as a parameter on your Mammal constructor, and set it up there, or better, just use class.name directly and ignore name_type. You would end up with something like this:
Code: Select all
require 'MiddleClass.lua'
Animal = class('Animal')
function Animal:initialize(name,color)
self.name = name
self.color = color
end
function Animal:describe()
print('My name is ' .. self.name .. '.')
print('I am of a ' .. self.color .. ' color.')
end
hasWings = {}
function hasWings.fly()
print('flap flap flap!')
end
hasWings.canFly = true
Mammal = Animal:subclass('Mammal')
function Mammal:initialize(name,color,sound)
super(self,name,color)
self.sound = sound or nil
end
function Mammal:describe()
super(self)
print('I am a ' .. self.class.name .. '.')
if self.sound ~= nil then
print('I can speak!')
self:speak(5)
else
print("I can't speak!")
end
if self.canFly == true then
print('I can fly!');
self:fly();
else
print("I can't fly!");
end
end
function Mammal:speak(count)
count = count or 1;
if self.sound ~= nil then
repeat
print(self.sound .. '!!');
count = count - 1
until count == 0
else
print('...!!!');
end
end
--make a dog
Dog = Mammal:subclass('Dog')
function Dog:initialize(name,color,sound)
super(self,name,color,sound)
end
local dog1 = Dog:new('Billy','white','wolf')
dog1:describe()
print('----')
--make a bat
Bat = Mammal:subclass('Bat')
function Bat:initialize(name,color,sound)
super(self,name,color,sound)
end
Bat:includes(hasWings)
local bat1 = Bat:new('John','brown')
bat1:describe()
When I write def I mean function.
Who is online
Users browsing this forum: No registered users and 3 guests