Lua 에서 실현 류 의 원리

17579 단어 lua
주소 http://wuzhiwei.net/lua_make_class/
좋아, metatable 을 투철 하 게 말 해서 나 는 마침내 알 게 되 었 다.
------------------------------------------------------------
 
Lua 에는 개념 이 없 지만 Lua 자체 의 언어 특성 을 이용 하여 실현 할 수 있다 .
다음은 Lua 에서 실현 류 의 원 리 를 상세 하 게 설명 하고 관련 된 세부 점 은 나 누 어 말 하 며 Lua 에서 실현 류 에 대한 이해 가 어 려 운 학생 들 이 의문 을 풀 것 이 라 고 믿 습 니 다.
클래스 가 뭐 예요?
클래스 를 실현 하려 면 클래스 가 무엇 인지 알 아야 한다.
내 가 보기에 클래스 는 자신 이 정의 하 는 변수 유형 이다.그것 은 속성 과 방법 을 약 속 했 고 속성 과 방법의 집합 이다.
모든 방법 은 이름 이 필요 합 니 다. 익명 함수 라 도 실제로 이름 이 있 습 니 다.이것 은 방법 이름과 방법 함수 의 키 맵 관 계 를 형성 했다. 즉, 방법 명 은 키 이 고 매 핑 의 값 은 방법 함수 이다.
예 를 들 어 한 가지 유형 은 사람 이 고 사람 이 말 하 는 방법 이 있다. 그러면 사람 (Person) 은 하나의 유형 이 고 말 (talk) 은 그의 방법 명 이 며 말 함 수 는 그의 실제 말 에서 실 행 된 내용 이다.
사람 에 게 도 하나의 속성 이 있다. 예 를 들 어 성별, 성별 은 하나의 키 (sex) 이 고 성의 실제 값 은 바로 이 키 에 대응 하 는 내용 이다.
클래스 가 실제로 키 값 이 맞 는 집합 이라는 것 을 이해 하 였 습 니 다. 우 리 는 Lua 에서 가 져 온 시계 로 클래스 를 실현 할 생각 을 하기 어렵 지 않 습 니 다.
실례 가 무엇 입 니까?
만약 클래스 가 실제 키 맵 의 표 라 는 것 을 이해 했다 면, 우 리 는 인 스 턴 스 가 무엇 인지 다시 이해 합 니 다.
인 스 턴 스 는 클래스 의 속성 과 방법 을 가 진 집합 이자 표 이다.듣 기 에 클래스 와 차이 가 많 지 않 은 것 같은 데?
전체 국면 은 하나의 집합 만 있 고 하나님 에 해당 하 며 전체 국면 은 하나의 메모리 만 있다.그리고 실례 는 평범 하 다. 천하 에 그렇게 많은 사람 이 있 으 니 A 에 게 한 마디 하 라 고 하면 A 는 그의 말 하 는 방법 을 실 행 했 지만 B 의 말 에 영향 을 주지 않 는 다.그들 은 실례 이기 때문에 서로 다른 메모 리 를 분배 하고 있다.
쓸데없는 말 을 많이 했 는데 사실은 인 스 턴 스 는 클래스 에서 만들어 진 값 입 니 다. 클래스 가 아 닌 유형 으로 상상 해 보 세 요.
문법 사탕 두 개
인간 을 만들어 보 자.  Person
 
Person = {name="     "}

 
상기 코드 는 Person 을 하나의 표 로 초기 화 합 니 다. 이 표 는 name 키 를 가지 고 있 습 니 다. 기본 값 은 " " 입 니 다.
막말 로 인간 은 이름 이라는 속성 을 가지 고 있다.
인간 에 게 말 하 는 기능 을 하나 더 부여 하 자.
 
Person.talk = function(self, words)

    print(self.name.." :"..words)

end

 
이상 코드 는 Person 표 에 키 쌍 을 추가 하고 키 는 talk 이 며 값 은 함수 입 니 다.
자, 호출 만 하면 Person.talk(Person, " ") 인쇄 됩 니 다. : 그러나 프로그램 을 쓸 때 모두 function 를 앞 에 두 는 것 이 습관 이 되 었 다. 이것 이 바로 함수 의 문법 사탕 이다.
 
function Person.talk(self, words)

    print(self.name.." :"..words)

end

 
이것 은 위의 함수 와 등가 로 정의 되 어 있 지만 이렇게 쓰 면 알 아 보기 어렵다 talk 는 사실은 Person 표 의 키 이 고 그 에 대응 하 는 값 은 함수 이다.
물론 입 은 모두 자신 에 게 자 라 는 것 이기 때문에 말 은 자신 만 할 수 있 고 자신 이 입 을 벌 리 고 다른 사람 이 말 할 수 없 기 때문에 매번 self 인 자 를 전달 하 는 것 은 정말 아름 답지 않 아서 가짜 문법 사탕 이 등장 한다.
우 리 는 인간 의 말 하기 기능 도 이렇게 정의 할 수 있다.
 
function Person:talk(words)

    print(self.name.." :"..words)

end

 
이것 은 위의 두 단락 코드 와 모두 등가 이다. 그 변 화 는 self 의 매개 변수 가 적 고 점 Person.talk 을 사칭 Person:talk 으로 바 꾸 었 다.
그러나 함수 안에 서 는 여전히 사용 할 수 있다 self. : 대체 . 를 사용 할 때 함수 의 매개 변수 목록 의 첫 번 째 매개 변 수 는 더 이상 words 이 아니 라 Lua 는 자동 으로 self 를 첫 번 째 매개 변수 로 한다.이 self 매개 변 수 는 이 함수 의 실제 호출 자 를 나타 낸다.
그래서 우리 가 호출 Person:talk(" ")Person.talk(Person, " ") 은 등가 이다. 이것 이 바로 가짜 문법 사탕 이 가 져 온 편리 함 이다.
어떻게 표 의 요 소 를 찾 습 니까?
루 아의 표 에서 키 에 해당 하 는 값 을 어떻게 찾 는 지 이해 해 야 합 니 다.
만약 에 우리 가 표 p 에서 talk 이 키 에 대응 하 는 값 을 찾 으 려 면 아래 의 흐름 도 를 보십시오.
 
p    talk   ?   -->   talk    

        |

         

        |

p      metatable?   -->    nil

        |

         

        |

 p metatable    __index   ?    -->    nil

        |

         

        |      

 p metatable  __index           talk   ?    -->   nil

        |

         ,  getmetatable(p).__index.talk

 
이상 의 내용 을 이해 하 는 것 이 본문의 중점 이 며, 네가 기억 할 때 까지 반복 해서 읽 는 것 이다.metatable__index 두 가지 신기 한 것 으로 인해 루 아 는 현재 표 에 이 키 가 존재 하지 않 을 때 되 돌아 오 는 값 을 찾 을 수 있 습 니 다.
다음은 이 언어 특성 을 말씀 드 리 겠 습 니 다.
metatable 에 대한 이해
metatable 이 뭐 예요?
metatable 의 중국어 이름 은 원 표 라 고 합 니 다.그것 은 하나의 단독 유형 이 아니 라 원 표 는 사실 하나의 시계 이다.
우 리 는 Lua 에서 표 의 조작 이 유한 하 다 는 것 을 알 고 있다. 예 를 들 어 표 는 직접 추가 할 수 없고 비교 조작 을 할 수 없다 는 등 이다.
원 표 의 역할 은 표 의 이미 정 해진 조작 을 증가 하고 바 꾸 는 것 이다.원 표 시 계 를 설정 해 야 원 표 의 영향 을 받 아 자신의 행 위 를 바 꿀 수 있다.
전역 방법 metatable 을 통 해 표 setmetatable(t, m) 의 원 표를 표 t 로 설정 합 니 다.다른 전역 방법 m 을 통 해 원 표 getmetatable(t) 를 되 돌려 줍 니 다.
메모: 모든 시 계 는 원 표를 설정 할 수 있 지만 새로 만 든 빈 시 계 는 설정 하지 않 으 면 원 표 가 없습니다.
원 법
원 표 는 하나의 표 로 서 임의의 유형의 키 값 을 가 질 수 있 습 니 다. 진정 으로 설 정 된 표 에 미 치 는 영향 은 Lua 가 규정 한 원 방법 키 값 입 니 다.
이 키 들 은 Lua 가 규정 한 키 입 니 다. 예 를 들 어 앞에서 말 한 m, __index, __add 등 입 니 다.이 키 들 은 모두 쌍 슬 래 쉬 __concat 를 접두사 로 한다.그 에 대응 하 는 값 은 하나의 함수 로 메타 방법 (metamethod) 이 라 고 불 립 니 다. 이 메타 방법 들 은 표 에 대한 사용자 정의 작업 을 정의 합 니 다.
예 를 들 어 앞에서 말 한 __ 키 는 Lua 에서 해당 하 는 메타 방법 으로 실 행 될 때 표 에 존재 하지 않 는 키 를 찾 을 때 해 야 할 동작 입 니 다.다음 코드 고려:
 
--    m

m = {}

--     __index    

--        ,    "undefined"

m.__index = function ( table, key )

  return "undefined"

end  

 

-- pos

pos = {x=1, y=2}

--

--  z  pos ,      nil

print(pos.z) -- nil

-- pos     m

setmetatable(pos, m)

--    pos      z,    pos   ,

--     __index  ,           ,  “undefined”

print(pos.z) -- undefined

  __index 표 에는 pos 이 키 가 없 었 다. z 의 원 표를 pos 로 설정 하고 mm 대응 하 는 방법 을 설정 하면 얻 지 못 한 모든 키 가 되 돌아 올 것 이다 __index.
이상 에서 우 리 는 원 표 의 “undefined” 속성 이 실제 적 으로 표 에 키 를 찾 지 못 할 때의 행 위 를 배치 한 것 을 알 게 되 었 다.
주의: 원 표 의 __index 속성 에 대응 하 는 것 도 하나의 표 일 수 있 습 니 다.
밤 을 하나 더 들 어 원 표 와 원 방법 에 대한 이 해 를 강화 하고 __index 키 를 눌 러 다음 코드 를 고려 하 시기 바 랍 니 다.
 
--    m,   __add        

local m = {

  __add = function(t1, t2)

    local sum = {}

    for key, value in pairs(t1) do

      sum[key] = value

    end

 

    for key, value in pairs(t2) do

      if sum[key] then

        sum[key] = sum[key] + value

      else

        sum[key] = value

      end

    end

    return sum

  end

}

 

-- table1 table2    m

local table1 = setmetatable({10, 11, 12}, m)

local table2 = setmetatable({13, 14, 15}, m)

 

--         +    ,      ,     !

for k, v in pairs(table1 + table2) do

  print(k, v)

end

--print

--1 23

--2 25

--3 27

 
표 자 체 는 __add 로 연결 하여 계산 할 수 없 지만 원 표 의 + 방법 을 정의 하고 __add 이 조작 을 원 하 는 표 에 이 르 면 그 표 들 은 덧셈 을 할 수 있다.
원 표 의 setmetatable 속성 은 표 에 + 번 호 를 사용 할 때의 행 위 를 정의 하기 때문이다.
유형의 실현 수단
자, 앞의 내용 을 의문 없 이 읽 었 다 고 가정 하면 우 리 는 본론 으로 들 어가 기 시작 합 니 다.
먼저 독립 적 으로 생각 하 세 요. 우 리 는 어떻게 Lua 류 를 실현 해 야 합 니까?
생각 하 는 중...
여러 가지 깔개 를 깔 고 나 면 우리 의 종 류 는 하나의 표 로 각종 속성 과 방법 을 정의 한다.우리 의 인 스 턴 스 도 하나의 표 입 니 다. 그리고 우 리 는 하나의 메타 표 로 인 스 턴 스 에 설정 하고 클래스 의 __add 값 을 자신 으로 설정 합 니 다.
예 를 들 어 인간:
 
--  Person __index   

Person.__index = Person  

 

--p     

local p = {}

 

--p      Person

setmetatable(p, Person)

 

p.name = "   "

 

--p       ,  talk   

--  p   ,     __index      Person

-- Person   talk   ,      Person talk  

--    self    p,p name   “   ”

p:talk("     ")

 

--      

--    :     

 
편 의 를 위해 서, 우 리 는 인류 에 게 창설 함수 __index 를 주 었 다.
 
function Person:create(name)

    local p = {}

    setmetatable(p, Person)

    p.name = name

    return p

end

 

local pa = Person:create("   ")

local pb = Person:create("   ")

pa:talk("     ") --    :     

pb:talk("     ") --    :     

이렇게 하면 우 리 는 Person 류 로 pa 와 pb 두 개의 인 스 턴 스 를 쉽게 만 들 수 있 습 니 다. 이 두 인 스 턴 스 는 모두 Person 의 속성 과 방법 을 가지 고 있 습 니 다.
-----------------------------
이 글 은 metatable 에 대한 이해 에 매우 도움 이 된다.그러나 저 는 개인 적 으로 실현 류 는 metatable 로 너무 복잡 하고 lua 에서 class 로 직접 실현 하 는 것 이 더욱 뚜렷 하 다 고 생각 합 니 다.
예 를 들 어 제 가 클래스 Person 을 정의 합 니 다.
local Person = class("Person")

function Person:ctor()

    self.name = "     "

end

function Person:talk( words)

    print(self.name.." :"..words)

end

return Person

정의 가 다 된 후에 이렇게 호출 합 니 다.
import("..module.Person") --      Person ,       

local
pa= Person.new() pa.name = " " pa:talk(" ") -- :
local pb= Person.new() 
pb.name
= " "
pb:talk(
" ") -- :

나 는 이것 이 metatable 보다 더욱 명확 하 다 고 생각한다. 너 는 어떻게 생각 하 니?

좋은 웹페이지 즐겨찾기