I'll put it to you this way, if your examples managed to confuse both myself and pgimeno - it doesn't speak good for the code.
Basically you're doing a simple __index fallback to another table.
It won't work for more than one level of inheritance, so you can't make a subclass of "subclass".
Object inheritance
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
Re: Object inheritance
What I use :
class.lua
vehicle.lua
car.lua
main.lua
class.lua
Code: Select all
local Class = {}
function Class:new() end
function Class:extend() local obj = {} obj.__call, obj.__index, obj.super = self.__call, obj, self return setmetatable(obj, self) end
function Class:__index(v) return Class[v] end
function Class:__call(...) local obj = setmetatable({}, self) obj:new(...) return obj end
return Class
Code: Select all
Vehicle = Class:extend()
function Vehicle:new(nb_of_wheels, name)
self.nb_of_wheels = nb_of_wheels
self.name = name
end
function Vehicle:update(dt) print(self.name, self.nb_of_wheels) end
function Vehicle:draw() love.graphics.rectangle("line", 10, 10, 10, 10) end
Code: Select all
Car= Vehicle:extend()
function Car:new(name) self.super.new(self, 4, name) end
function Car:update(dt) self.super.update(self, dt) end
function Car:draw() self.super.draw() end
Code: Select all
function love.load()
require("class")
require("vehicle")
require("car")
my_car = Car("Ferrari")
end
function love.update(dt) my_car:update(dt) end
function love.draw() my_car:draw() end
Re: Object inheritance
To clarify, I was confused by Schwender.exe's code, not by TheHUG's code, especially regarding initialization of members. It made me think that Player was an instance, not a class.
Re: Object inheritance
Of course you can, anything created with subobject:new will have subobject as it's metatable,and subobject __index attribute will be itself. You can then use that object as a subclass, defining new methods for it, which anything made with subsubobject:new will inherit.ivan wrote: ↑Mon Jul 08, 2019 1:44 pm I'll put it to you this way, if your examples managed to confuse both myself and pgimeno - it doesn't speak good for the code.
Basically you're doing a simple __index fallback to another table.
It won't work for more than one level of inheritance, so you can't make a subclass of "subclass".
It was the first result back when I googled 'classes in lua' :https://www.lua.org/pil/16.1.html . it's seems to be a fairly standard way to do it, and I still prefer it since it's simple and explicit.
Re: Object inheritance
Oops sorry pgimeno was talking about somebody else. And no Lua doesn't have classes or instances.
I don't follow your explanation so you have to show me a code example with more than one layer of inheritance.
I don't follow your explanation so you have to show me a code example with more than one layer of inheritance.
- zorg
- Party member
- Posts: 3465
- Joined: Thu Dec 13, 2012 2:55 pm
- Location: Absurdistan, Hungary
- Contact:
Re: Object inheritance
Does this qualify for multiple inheritance? I typed it up and tested it in 5 mins:
Code: Select all
-- "class" A
local A = {} -- "methods/members" for "class instances"
A.bar = function() print "A!" end -- example of above
local mtA = {__index = A} -- one metatable to make instances access these methods
local newA = function() return setmetatable({}, mtA) end -- set instance to access class methods/members if it itself doesn't contain such a key.
-- "class" B
local B = {}
B.baz = function() print "B!" end
local mtB = {__index = B}
setmetatable(B, mtA) -- set class B's method/member table to have class A's method/member table as a fallback.
local newB = function() return setmetatable({}, mtB) end
local foo
foo = newA()
foo:bar()
foo = newB()
foo:baz()
foo:bar() -- method "bar" in class "A" called through fallback index metamethod defined on class "B"'s own methodlist
-- This can be extended to more than one "round", e.g. an instance of class C falling back to class B falling back to class A's
-- class methods or members.
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Re: Object inheritance
Looks fine and yes this would work thanks to the following line:
So you can have as many layers of inheritance as you want as long as the metatables fallback sequentially to the parent object.
I would call this "layers of inheritance" since "multiple inheritance" usually refers to something different.
Code: Select all
setmetatable(B, mtA) -- set class B's method/member table to have class A's method/member table as a fallback.
I would call this "layers of inheritance" since "multiple inheritance" usually refers to something different.
- zorg
- Party member
- Posts: 3465
- Joined: Thu Dec 13, 2012 2:55 pm
- Location: Absurdistan, Hungary
- Contact:
Re: Object inheritance
Yeah, the diamond of death thing; i guess even that could be possible, depending on whether you can set __index to be a function and check multiple "parent" tables defined by the class itself.. but then you'd probably also want a way to programatically set which other "classes" one should search for potentially missing members/methods, the order of the definitions mattering and such. (or you could just hard-code it)
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Re: Object inheritance
Never had any use for multiple inheritance myself. But simple inheritance like in your code example can be very useful.
Re: Object inheritance
An example of more levels of inheritance would be:
internally when BouncingCollider:new() is called it finds that BouncingCollider.new == nil, so it looks in getmetatable(BouncingCollider).__index (i.e. Collider) for .new. Since that is also nil, it will check getmetatable(Collider).__index (i.e. Object) and find the .new function there.
There are several variations you can do, including some where the boundary between instance and class is clearer and/or enforceable, though I don't really see the need. That's one advantage of being explicit - it preserves customizability so you can code with your preference.
One variation I used for a while was to leave out self.__index = self in :new and specifically set the metatable and __index for each subclass, such that :new would only work when invoked on the class, not on an instance, but I ended up liking this better, they're all just tables after all.
Code: Select all
Object = {}
function Object:new(x, y)
local o = {x=x, y=y}
setmetatable(o, self)
self.__index = self
return o
end
Collider = Object:new() -- Collider inherits Object's :new method
function Collider:collide(...)
...
end
a_collider = Collider:new() -- an instance of Collider
BouncingCollider = Collider:new(new_default_an_arg) -- creates BouncingCollider and sets its metatable to Collider, inheriting :new and :collide
--override :collide
function BouncingCollider:collide(...)
--bounce and then
getmetatable(self).collide(self, ...)
end
a_bouncing_collider = BouncingCollider:new() -- works
There are several variations you can do, including some where the boundary between instance and class is clearer and/or enforceable, though I don't really see the need. That's one advantage of being explicit - it preserves customizability so you can code with your preference.
One variation I used for a while was to leave out self.__index = self in :new and specifically set the metatable and __index for each subclass, such that :new would only work when invoked on the class, not on an instance, but I ended up liking this better, they're all just tables after all.
Who is online
Users browsing this forum: Ahrefs [Bot] and 3 guests