About OOP and interface
About OOP and interface
Hi guys, i have some questions about lua, I read in some places about oop and lua, i want to use the design pattern strategy, but i dont find anything about inheritance, polymorphism or interfaces, have it on lua? if not what i can use to simulate strategy.
Re: About OOP and interface
Strategy pattern is all about polymorphism, you don't really need inheritance or interfaces for it.
Is this the strategy pattern? Sure, we can tell a "guy" to "attack" and we don't care about the details of how it happens.
Did we need inheritance? No, we have first-class functions so we can just attach whatever methods we want to our objects without any dedicated constructors or inheritance.
Did we need interfaces? Nope. From the last two lines of code, we know there's an implicit contract with objects representing "guys." We expect a "guy" to have an "attack" function with a specific function signature, and a "name" field that's a string. We can use this implicit contract without formally specifying it in an interface.
Code: Select all
local function attackWithKnife (self, target)
print(self.name .. ' stabs ' .. target.name)
end
local function attackWithGun (self, target)
print(self.name .. ' shoots ' .. target.name)
end
local guyA = {
name = 'Stabbicus',
attack = attackWithKnife,
}
local guyB = {
name = 'Blastimus',
attack = attackWithGun,
}
guyA:attack(guyB)
guyB:attack(guyA)
Did we need inheritance? No, we have first-class functions so we can just attach whatever methods we want to our objects without any dedicated constructors or inheritance.
Did we need interfaces? Nope. From the last two lines of code, we know there's an implicit contract with objects representing "guys." We expect a "guy" to have an "attack" function with a specific function signature, and a "name" field that's a string. We can use this implicit contract without formally specifying it in an interface.
Re: About OOP and interface
Thx man, I am very attached to some java and .net paradigms, I did not think this way, perhaps lack of study of language or vice in specific methods. so, really thx you.
Re: About OOP and interface
No problem, it was an interesting question
I think most of the traditional design patterns become much simpler when you embrace dynamic types and first-class functions. Just for the record, though, you could also do this in a more "classical" way.
If you ask me, that's a hell of a lot of work for very little gain. If you like the idea of having KnifeGuy and GunGuy classes, you might consider factory functions instead (factory pattern is also much simpler with first-class functions and dynamic typing).
If you miss inheritance with these factory functions, try using decorators instead (they'll also be much less work than you're used to).
I think most of the traditional design patterns become much simpler when you embrace dynamic types and first-class functions. Just for the record, though, you could also do this in a more "classical" way.
Code: Select all
-- defines a class with optional single inheritance
local function Class (superclass)
local meta = { __index = {} }
return setmetatable(meta.__index, {
__call = function (_, ...)
local instance = setmetatable({}, meta)
if instance.init then
instance:init(...)
end
return instance
end,
__index = superclass
})
end
-- our Weapon interface is just a doc block
-- @interface Weapon
-- @method init(Guy owner)
-- @method attack(Guy target)
-- Knife and Gun implement Weapon
-- @class Knife
-- @implements Weapon
local Knife = Class()
-- @constructor
-- @param Guy owner
function Knife:init (owner)
self.owner = owner
end
function Knife:attack (target)
print(owner.name .. ' stabs ' .. target.name)
end
-- @class Gun
-- @implements Weapon
local Gun = Class()
-- @constructor
-- @param Guy owner
function Gun:init (owner)
self.owner = owner
end
function Gun:attack (target)
print(owner.name .. ' shoots ' .. target.name)
end
-- @class Guy
local Guy = Class()
-- @constructor
-- @param string name
function Guy:init (name)
self.name = name
self.weapon = nil -- this does nothing, it's just here for documentation
end
function Guy:attack (target)
if self.weapon then self.weapon:attack(target) end
end
-- @class KnifeGuy
-- @extends Guy
local KnifeGuy = Class(Guy)
function KnifeGuy:init (name)
Guy.init(self, name) -- call the superclass constructor
self.weapon = Knife(self)
end
-- @class GunGuy
-- @extends Guy
local GunGuy = Class(Guy)
function GunGuy:init (name)
Guy.init(self, name) -- call the superclass constructor
self.weapon = Gun(self)
end
local guyA = KnifeGuy('Stabbicus')
local guyB = GunGuy('Blastimus')
guyA:attack(guyB)
guyB:attack(guyA)
Code: Select all
local function attackWithKnife (self, target)
print(self.name .. ' stabs ' .. target.name)
end
local function attackWithGun (self, target)
print(self.name .. ' shoots ' .. target.name)
end
local function KnifeGuy (name)
return {
name = name,
attack = attackWithKnife,
}
end
local function GunGuy (name)
return {
name = name,
attack = attackWithGun,
}
end
Who is online
Users browsing this forum: Ahrefs [Bot], Google [Bot] and 7 guests