Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 如何在Lua中实现OO?_Oop_Lua - Fatal编程技术网

Oop 如何在Lua中实现OO?

Oop 如何在Lua中实现OO?,oop,lua,Oop,Lua,Lua没有对OO的内置支持,但它允许您自己构建它。你能分享一下实现OO的一些方法吗 请每个答案写一个例子。如果您有更多的示例,请发布另一个答案。我喜欢将OOP视为容器(对象)内的数据封装,以及可以使用此数据执行的操作子集。还有很多,但是让我们假设这个简单的定义就是全部,并用它在Lua中构建一些东西(另外,对其他OO实现的一些熟悉对读者来说也是一个很好的提升) 任何稍微接触过Lua的人都可能知道,表是存储键值对的一种简洁方式,结合字符串,事情开始变得非常有趣: local obj = {} --

Lua没有对OO的内置支持,但它允许您自己构建它。你能分享一下实现OO的一些方法吗


请每个答案写一个例子。如果您有更多的示例,请发布另一个答案。

我喜欢将OOP视为容器(对象)内的数据封装,以及可以使用此数据执行的操作子集。还有很多,但是让我们假设这个简单的定义就是全部,并用它在Lua中构建一些东西(另外,对其他OO实现的一些熟悉对读者来说也是一个很好的提升)

任何稍微接触过Lua的人都可能知道,表是存储键值对的一种简洁方式,结合字符串,事情开始变得非常有趣:

local obj = {} -- a new table
obj["name"] = "John"
obj["age"] = 20
-- but there's a shortcut!
print("A person: " .. obj.name .. " of the age " .. obj.age)
作为表中键的字符串值的访问方式与C++中的结构成员或C++/Java及类似语言中的对象的公共成员非常相似

现在来看一个很酷的魔术:让我们将其与匿名函数结合起来

-- assume the obj from last example
obj.hello = function () 
   print("Hello!")
end

obj.goodbye = function ()
   print("I must be going.")
end

obj.hello()
obj.goodbye()
太棒了,对吧?现在我们有了将函数存储在表中的方法,您可以再次看到它类似于其他OOP语言中使用的方法。但是缺少了一些东西。我们如何在方法定义中访问属于对象的数据?这通常通过将表中函数的签名更改为以下内容来解决:

-- assume the obj from last example
obj.inspect = function (self)
   print("A person: " .. self.name .. " of the age " .. self.age)
end

obj.hello = function (self) 
   print(self.name .. ": Hello! I'm " .. self.name)
end

obj.goodbye = function (self)
   print(self.name .. ": I must be going.")
end

-- now it receives the calling object as the first parameter
obj.inspect(obj) -- A person: John of age 20
obj.hello(obj) -- John: Hello! I'm John
obj.goodbye(obj) -- John: I must be going
class = {} -- Will remain empty as class
mt = {} -- Will contain everything the instances will contain _by default_

mt.new = function(self,foo)
    local inst={}
    if type(foo) == "table" then
         for k,v in pairs(foo) do
             inst[k]=v
         end
    else
        inst.foo=foo
    end
    return setmetatable(inst,getmetatable(class))
end

mt.print = function(self)
    print("My foo is ",self.foo)
end

mt.foo= 4 --standard foo

mt.__index=mt -- Look up all inexistent indices in the metatable

setmetatable(class,mt)

i1=class:new() -- use default foo
i1:print()

i2=class:new(42)
i2:print()

i3=class:new{foo=123,print=function(self) print("Fancy printing my foo:",self.foo) end}
这以一种简单的方式解决了它。也许与Python中的工作方式类似(方法总是有一个显式的自我)可以帮助您学习如何在Lua中工作。但是,在我们的方法调用中显式地传递所有这些对象不是很不方便吗?是的,这也让我感到困扰,所以有另一条捷径可以帮助您使用OOP:

obj:hello() -- is the same as obj.hello(obj)

最后,我只是初步了解了如何做到这一点。如中所述,是有关此主题的优秀信息源,在这里您可以了解如何实现本答案中忽略的OOP的另一个重要方面(私有成员、如何构造对象、继承等等)。请记住,这种方法只是Lua哲学的一小部分,它为您提供了能够构建更高级结构的简单正交工具。

对于快速而肮脏的oo实现,我做了如下操作-

function newRGB(r,g,b)
  return {
    red=r;
    green=g;
    blue=b;
    name='';
    setName = function(self,name)
      self.name=name;
    end;
    getName = function(self)
      return self.name;
    end;
    tostring = function(self)
      return self.name..' = {'..self.red..','..self.green..','..self.blue..'}'
    end
  }
end
然后可以像这样使用-

blue = newRGB(0,0,255);
blue:setName('blue');

yellow = newRGB(255,255,0);
yellow:setName('yellow');

print(yellow:tostring());
print(blue:tostring());

对于功能更全面的方法,我将使用eemrevnivek提到的oo库。您还可以找到一个简单的类函数,该函数介于完全库函数和快速脏函数之间。

我使用的方法通常如下所示:

-- assume the obj from last example
obj.inspect = function (self)
   print("A person: " .. self.name .. " of the age " .. self.age)
end

obj.hello = function (self) 
   print(self.name .. ": Hello! I'm " .. self.name)
end

obj.goodbye = function (self)
   print(self.name .. ": I must be going.")
end

-- now it receives the calling object as the first parameter
obj.inspect(obj) -- A person: John of age 20
obj.hello(obj) -- John: Hello! I'm John
obj.goodbye(obj) -- John: I must be going
class = {} -- Will remain empty as class
mt = {} -- Will contain everything the instances will contain _by default_

mt.new = function(self,foo)
    local inst={}
    if type(foo) == "table" then
         for k,v in pairs(foo) do
             inst[k]=v
         end
    else
        inst.foo=foo
    end
    return setmetatable(inst,getmetatable(class))
end

mt.print = function(self)
    print("My foo is ",self.foo)
end

mt.foo= 4 --standard foo

mt.__index=mt -- Look up all inexistent indices in the metatable

setmetatable(class,mt)

i1=class:new() -- use default foo
i1:print()

i2=class:new(42)
i2:print()

i3=class:new{foo=123,print=function(self) print("Fancy printing my foo:",self.foo) end}

好的,结论:有了元表和一些聪明的想法,任何事情都是可能的:当使用类时,元表是真正的魔法。

我看到的最好的解决方案不是在Lua中实现OO,因为它不是自然的、不完整的,因此需要很多线;相反,在C++中使用LababRead或LuabDin实现它,在那里它是自然的和强大的!p> 使用LuaBridge的简约示例:

m.class_<MyClass>("MyClass")
.constructor<void (*) (/* parameter types */)>()
.method("method1", &MyClass::method1)
.property_rw("property2", &MyClass::getter2, &MyClass::setter2)
.property_ro("property3", &MyClass::property3)

还支持一级继承…

这已经得到了回答,但无论如何,这里是我的oop实现:

该库提供了创建类、实例、继承、多态性和(原语)混合的最低要求,并具有可接受的性能

样本:

local class = require 'middleclass'

local Person = class('Person')

function Person:initialize(name)
  self.name = name
end
function Person:speak()
  print('Hi, I am ' .. self.name ..'.')
end

local AgedPerson = class('AgedPerson', Person) -- or Person:subclass('AgedPerson')

AgedPerson.static.ADULT_AGE = 18 --this is a class variable
function AgedPerson:initialize(name, age)
  Person.initialize(self, name) -- this calls the parent's constructor (Person.initialize) on self
  self.age = age
end
function AgedPerson:speak()
  Person.speak(self) -- prints "Hi, I am xx."
  if(self.age < AgedPerson.ADULT_AGE) then --accessing a class variable from an instance method
    print('I am underaged.')
  else
    print('I am an adult.')
  end
end

local p1 = AgedPerson:new('Billy the Kid', 13) -- this is equivalent to AgedPerson('Billy the Kid', 13) - the :new part is implicit
local p2 = AgedPerson:new('Luke Skywalker', 21)
p1:speak()
p2:speak()

我会给它加奖励,一旦我知道如何,那么上面的答案让我们说‘Abto一周’得到它:你的意思是像C++?好吧,最好不要卷入那场辩论:(Lua的PIL对此有详细的参考资料。它收集了大量关于如何在Lua中实现OOP的资源。有多种方法;您可以使用表、元表、代理表或闭包。也有像LOOP和ObjectLua这样的库,但是在参考设计中编写自己的或复制很容易。回答很好。I我想补充一点,您可以编写
函数obj:hello()**这里的东西**end
,而不是
obj.hello=function(self)**这里的东西**end
,这看起来更漂亮!
我喜欢将OOP看作是容器(对象)中数据的封装加上可以使用此数据执行的操作子集
,这通常称为基于对象的,因为它不是完整的OOP。有时也称为ADT(抽象数据类型)ADT处理简单,可以用几乎任何语言实现,除了缺少继承之外,它拥有所有需要的东西。IHO在LoA项目中包含C++以获得OOP是有点过火的。有些人会争论(包括我)。C++的OOP实际上是非常复杂的,实际上并不是真正的OOP原理。程序员也必须知道另一种语言来使用它,不是很好。这里有一个关于C++的好的读,它的OO实现是我见过的最简单最简单的解决方案。