Lua 에서 실현 류 의 원리
17579 단어 lua
좋아, 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
로 설정 하고 m
의 m
대응 하 는 방법 을 설정 하면 얻 지 못 한 모든 키 가 되 돌아 올 것 이다 __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 보다 더욱 명확 하 다 고 생각한다. 너 는 어떻게 생각 하 니?
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Neovim을 위한 자동 완성NeoVim으로 생산성을 높일 수 있는 가장 멋진 기능 중 하나는 자동 완성이므로 성능에 따라 플러그인을 선택할 수 있습니다. YouCompleteMe Coc.nvim 이 플러그인은 사용하기 좋지만 Javascrip...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.