2014-01-15 4 views
2
Sprite = {x = 0, y = 0, pos = {z=0}} 
function Sprite:new() 
    o = {} 
    setmetatable(o,self) 
    self.__index = self 
    return o 
end 
s1 = Sprite:new() 
s2 = Sprite:new() 

s1.x = 10 
s1.pos.z = 5 

print("s1.x", s1.x, "s2.x", s2.x, "s1.z",s1.pos.z, "s2.z", s2.pos.z) 

s2.x = 20 
s2.pos.z = 50 

print("s1.x", s1.x, "s2.x", s2.x, "s1.z",s1.pos.z, "s2.z", s2.pos.z) 

에서 테이블 속성을 상속 할 수 없습니다, 나는 x(int),y(int),pos(table) 3 속성이 클래스 Sprite를 정의하지만 두 객체 s1,s2를 초기화하기 때. 나는 그들이 pos 속성을 공유하고있는 것을 발견했습니다. s1.pos.zs2.pos.z 그래서, 변경되는 경우,위의 코드에서 부모

s1.x 10 s2.x 0 s1.z 5 s2.z 5 
s1.x 10 s2.x 20 s1.z 50 s2.z 50 

s1s2 자신의 x,y 속성을 가지고 있지만, pos 속성을 공유 : 당신이 코드를 실행하면

, 그것을 인쇄 할 수 있습니다.

어떻게 해결할 수 있습니까?

답변

-1

Lua는 테이블을 공유하고 (참조로 유지) 변수를 복사합니다. 메소드에 대해 메타 테이블을 사용하고 오브젝트 테이블에 필드를 복사하는 필드를 유지하십시오.

Sprite = { 
    instanceData = { x = 0, y = 0, pos = {z = 0} }, 
    method = function(self) print("do smth with "..self) end 
} 

function Sprite:new() 
    local o = deepCopy(self.instanceData) 
    setmetatable(o,self) 
    self.__index = self 
    return o 
end 

딥 카피 구현은 스프라이트는 따라서 당신이 "클래스 폭"항목으로 스프라이트 테이블 생각할 수있는 클래스를 나타냅니다 wiki/CopyTable

+0

'self .__ index = self'는'Sprite : new' 외부에서 수행되어야합니다. – lhf

+0

그러나 클래스의 모든 데이터를 복사하면'__index'는 어떤 목적으로 사용됩니까? 결코 부름을받지 않을 것입니다. – lhf

+0

@lhf 필드 값 (instanceData) 만 복사합니다. 메서드를 복사 할 필요가 없으므로 metatable이 메서드에 더 좋습니다. 그것은 클래스 테이블을 만드는 더 명확한 해결책이 될 것이지만, 그것의 간단한 예입니다. 어쩌면 나중에 제공 할 것입니다. – Seagull

3

Sprite:new에서 변수 self의 값은 항상 Sprite입니다. 따라서 self.posSprite.pos을 말합니다. o.pos={}으로 변경해보십시오. 또한 o을 로컬로 설정하는 것을 고려해보십시오.

0

찾을 수 있습니다 그들은 모두 "인스턴스"에 의해 공유됩니다. 인스턴스 특정 항목은 오 테이블에 있어야합니다 :

Sprite = {classX = 0, classY = 0} -- class; vars shared by all instances 
function Sprite:new() 
    o = {pos = {z=0}} 
    setmetatable(o,self) 
    self.__index = self 
    return o 
end 

정말 그렇게 모든 인스턴스가 동일한 가치와 하나 개의 인스턴스에 의해 변경 사항이 볼 수 것입니다 볼, 기준 레벨에서 공유 의미 하는가 "공유"고 주 다른 모든. 테이블에 넣은 OTOH 데이터는 인스턴스마다 있습니다. 이것을 Sprite.new()에두면 모든 인스턴스가 동일한 필드를 갖지만 자체 데이터를 갖습니다. 한 인스턴스에 의한 변경은 다른 인스턴스에 영향을 미치지 않습니다.

즉, Sprite : new()는 self .__ newindex를 정의하지 않습니다. 따라서 Sprite.classX = 5는 모든 인스턴스에서 예상대로 표시되지만 s1.classX = 6은 s1에서만 볼 수 있습니다. 따라서 새 필드가 만들어져 Sprite의 필드가 숨겨집니다. 그때부터 Sprite.classX에 대한 변경 사항은 s1에서 더 이상 볼 수 없지만 Sprite.classX가 재정의되지 않은 다른 모든 인스턴스에 의해 변경됩니다. 그 주위를 얻으려면, 당신이 할 수 있습니다 : 당신이 함께 놀았 경우

function Sprite:new() 
    o = {pos = {z=0}} 
    setmetatable(o,self) 
    self.__index = self 
    self.__newindex = self 
    return o 
end 

루아 콘솔에서 당신이 볼 것이다 : 그 변화없이

> s1=Sprite:new() 
> s2=Sprite:new() 
> print(s1.classX, s2.classX) 
0  0 
> Sprite.classX=1 
> print(s1.classX, s2.classX) 
1  1 
> s1.classX=3 
> print(s1.classX, s2.classX) 
3  3 

, 마지막 출력은 3 일 "이 표시됩니다 "Sprite.classX에 대한 변경 사항은 s1에 표시되지 않습니다.

관련 문제