2017-05-22 1 views
1

루아에 MyClass 클래스를 만들고 싶습니다. 나중에 가져오고 사용할 수있는 myclass.lua입니다. 그것은 다음과 같은 방법으로 작업해야합니다루아에서 간단한 가져 오기 가능한 클래스를 만드는 방법은 무엇입니까?

local MyClass = require 'myclass' 
tab = {1,2,3} 
m = MyClass(tab) 

을 그러나, 나는 그것이 작동 및 오류 attempt to call global 'MyClass' (a table value)을 얻고있다 할 수 없습니다 루아 문서의 코드 다음과 같습니다.

내가 myclass.lua을 위해 지금까지 작성한 코드 :

local MyClass = {} 
MyClass.__index = MyClass 

function MyClass.__init(tab) 
    self.tab = tab or {} 
    setmetatable({},MyClass) 
    return self 
end 
return MyClass 

루아에서 클래스를 작성하는 방법을 예제의 과다있다하지만 난이 같은 차이를 이해하고 생각하지 않는다 구현 세부 사항에서 결과가 손실됩니다. 더 많거나 적은 평범한 방법이 있습니까?

답변

1

, 당신은 일반적으로 호출 할 수 없습니다 테이블 : 그냥 myclass.lua으로 업데이트합니다. 예를 들어,이 코드는 "local 't (테이블 값)을 호출하려고 시도합니다."라는 오류를 생성합니다.

local t = {} 
t() 

그러나 메타 테이블을 사용하여이 작업을 수행하는 방법이 있습니다.

local hello = {} 
local mt = {} -- The metatable 
mt.__call = function() 
    print("Hello!") 
end 
setmetatable(hello, mt) 
hello() -- prints "Hello!" 

함수처럼 테이블을 호출하려고하면 루아는 먼저 테이블에 메타 테이블이 있는지 확인합니다. 존재하면 해당 메타 테이블의 __call 속성에서 함수를 호출하려고 시도합니다. __call 함수의 첫 번째 인수는 테이블 자체이며 후속 인수는 테이블이 함수로 호출되었을 때 전달 된 인수입니다. 테이블에 메타 테이블이 없거나 메타 테이블에 __call 함수가 없으면 "로컬 't'호출 시도가 발생했습니다."오류가 발생합니다.

  1. 당신은 __init 대신 __call를 사용하려고 :

    귀하의 예제 코드는 세 가지 문제가 있습니다. 루아에는 __init 메타 메소드가 없습니다.

  2. __call에는 사용중인 매개 변수와 다른 매개 변수가 사용됩니다. __call 함수의 첫 번째 매개 변수는 테이블 자체입니다. function MyClass.__call(self, tab)을 사용하거나매개 변수를 암시 적으로 추가하는 콜론 구문 function MyClass:__call(tab)을 사용할 수 있습니다. 이 두 구문은 기능적으로 동일합니다.
  3. MyClass 테이블에 대한 메타 테이블을 설정하지 않았습니다. MyClass의 객체에 대한 메타 테이블을 설정하는 중이지만 그것이 메타 테이블이 MyClass 자체에 자동으로 설정된다는 것을 의미하지는 않습니다.

이 문제를 해결하려면 다음과 같이 뭔가를 할 수 :

local MyClass = {} 
setmetatable(MyClass, MyClass) 
MyClass.__index = MyClass 

function MyClass:__call(tab) 
    local obj = {} 
    obj.tab = tab or {} 
    setmetatable(obj, MyClass) 
    return obj 
end 

return MyClass 

이 MyClass에 완벽하게 유효한 루아하는 메타 테이블, 그 자체를 사용하여 설정합니다.

메타 테이블 시스템은 매우 유연하며 사용자가 원하는 모든 클래스/객체 체계를 가질 수 있습니다. 예를 들어 원한다면 모든 것을 인라인으로 처리 할 수 ​​있습니다.

local MyClass = {} 

setmetatable(MyClass, { 
    __call = function (class, tab) 
     local obj = {} 
     obj.tab = tab or {} 
     setmetatable(obj, { 
      __index = MyClass 
     }) 
     return obj 
    end 
}) 

return MyClass 

뿐만 아니라 간결되는 ,이 또한 클래스 테이블에 액세스 할 수있는 경우 사람들이 클래스의 메타 메소드를 변경할 수있는 장점이있다.

+0

테이블의 메타 테이블을 자체로 설정하고 __index 메타 메서드를 자체로 설정하면 약간의 단점이 있습니다 (큰 단점). 'local obj = MyClass {1, 2, 3}'는 실제로이 코드에서 잘 작동하지만,'obj.foo'를 인덱스하려고하면'foo'가'obj'에 존재하지 않는다고 봅니다. 'MyClass' 테이블에서'foo'를 검사합니다. obj의 __index를 설정합니다. 'MyClass'에서'foo'를 찾지 못하기 때문에'MyClass'의 __index를 봅니다. 이것은'MyClass'입니다. 루아는 이것이 무한 루프라는 것을 감지 할 정도로 똑똑하기 때문에 오류가 발생합니다. –

0

테이블에 사용할 수있는 메타 메서드가 없습니다. __init 다음 작업을 수행 할 때 :

m = MyClass(tab) 

MyClass.__call 메서드 정의를 찾습니다. 당신이 함수를 호출하는 것처럼 루아에서

local MyClass = {} 
MyClass.__index = MyClass 

function MyClass:__call(tab) 
    self.tab = tab or {} 
    setmetatable({},MyClass) 
    return self 
end 

return MyClass 
+0

예. 그렇지만 오류가있는 문제는 해결되지 않습니다. 이것을 가져 와서'local m = MyClass ({1,2,3}) '를 호출하십시오. – minerals

+2

@minerals'__call'에 대한 첫 번째 인수는 호출 된 "함수"입니다.이 경우에는 클래스입니다. 그래서'function MyClass .__ call (_, tab)'으로 변경하십시오. (나중에 "generic"생성자가 생기면,''_' '에 다른 이름을주고 그것을 사용하여''__call' 클래스가 인스턴스를 생성해야하는지 알 수 있습니다. – nobody

+0

작동하지 않습니다. '전역 MyClass' 오류를 호출하려고합니다. – minerals

관련 문제