재미있는 메타프로그래밍/6장
13459 단어 Ruby
제6장 금요일: 코드를 설명하는 코드
금요일 일정
1. 학급홍과의 연애
원래 학급홍은?
クラス定義内でselfを明示せずに呼び出せるキーワードのようなメソッド
ex) attr_accessor
거북이: "반 매크로는 방법이야!? 대단해. 나도 반 매크로를 독립적으로 만들 거야!"
거북이는 요즘 깜빡깜빡해서 자신이 언제 실례 변수를 만들었는지 잊어버렸다.따라서 실례 변수를 산열로 하고 시간 데이터를 저장할 수 있는 클래스 매크로를 실현하고자 한다.
Class Intern
attr_with_date :shimatomo
attr_with_date :kemako
end
intern = Intern.new
intern.shimatomo = 'shimada'
intern.kemako = 'miyatake'
intern.shimatomo[:val] # => 'shimada'
intern.shimatomo[:created_at] # => 3行上で作成した時のTime
2. eval을 사용하세요!
길흉: "그럼 우선 attr accessor를 단순한 방법으로 실현해 봅시다. 마침 여기서 EVAL을 사용해 보세요."
거북이:
"eval은 매개 변수로 전달되는 문자열을 코드로 실행합니다. 자세한 내용은 원 프로를 참조하십시오."
Q1. add_attr_with_date 방법의 행위는 다음과 같이 실현된다
class Intern; end
add_attr(Intern, :shimatomo)
intern = Intern.new
intern.shimatomo = 'shimada'
puts intern.shimatomo # 'shimada'
def add_attr_with_date(klass, attr)
eval "
#code...
"
end
# ヒント!
# hogeと言う名前のattrを受け取った場合に以下の様なメソッドを定義してほしい。
def hoge=(value)
@hoge = value
end
def hoge
@hoge
end
A1. add_attrdef add_attr_with_date(klass, attribute)
eval "
class #{klass}
def #{attribute}
@#{attribute}
end
def #{attribute}=(val)
@#{attribute} = valf
end
end
"
end
# 亀ちゃんさんの希望では次の様になる
def #{attr}=(val)
@#{attr} = {val: val, created_at: Time.now}
end
거북이: "eval을 사용하면 평소에 동적으로 설정할 수 없는 클래스 이름, 방법 이름, 실례 변수 이름을 동적으로 정의할 수 있습니다!"하지만 강력한 힘에
거북이&마장 "큰 책임과 함께!"
그러나 "eval에 전달된 문자열은 input 등 제3자의 입력을 포함할 때 코드에 악의가 있어도 직접 실행됩니다. 기본적으로 eval을 사용할 때 전달된 코드 문자열은 모두 자신의 입력임을 확인하십시오."
3. eval 사용을 중단하라!
거북이: "응, eval의 위험을 완전히 없애기는 어려울 것 같아."
좋습니다. "거북이, 현재 학급 동태변경 방법은 eval 이외에 또 있죠?"
아, 수요일에 한 거예요.
따라서 class eval을 사용하여 add attr with date를 변경하십시오.
A2.
def add_attr_with_date(klass, attribute)
klass.class_eval do
define_method "#{attribute}=" do |value|
attr_hash = { val: value, created_at: Time.new }
instance_variable_set("@#{attribute}", attr_hash)
end
define_method attribute.to_s do
instance_variable_get("@#{attribute}")
end
end
end
4. 유홍으로 만들어라!
거북이: "그런데 이런 반은 거시적인 게 아니야!!"
그래, 알았어, 알았어. 다음에 드디어 반에 가서 거시적으로 하자.
작은 거북이:"😲 」
안개: "드디어 반홍을 만들 때가 됐어요. 거북이의 눈이 더 눈부셔요."
Q3. 다음 변경 사항에 따라 방법을 클래스 매크로로 설정합니다.다음 코드는 예상한 결과입니다.
클래스를 매개 변수에 명확하게 전달하지 않음
- 정의 방법의 위치를 변경합니다(모든 클래스를 호출할 수 있음).
class Intern
attr_with_date :shimatomo
end
intern= Intern.new
intern.shimatomo = 'shimada'
intern.shimatomo[:val] # => 'shimada'
intern.shimatomo[:created_at] # => Timeオブジェクト
A3class Module # もしくはClassクラス
def add_attr_with_date(attr)
define_method(attr) do
instance_variable_get("@#{attr}")
end
define_method("#{attr}=")do |val|
instance_variable_set("@#{attr}", {
val: val,
created_at: Time.now
})
end
end
end
거북이: 다 했어!!!참, 클라스반이나 모듈반에서 방법을 정의하면 반 매크로로 사용할 수 있어요. 왜 그런지 아세요?
중산 선생"이것은 목요일 학급 정의에서 한 일이다. 루비 대상 모델에서 방법의 탐색 행위는 수신기의 특이류를 찾기 위해 방법을 호출한 다음에 특이한 슈퍼클래스를 탐색한 다음에 다음 다음 슈퍼클래스를 탐색하는 것이다. 이렇게 계속된다. 이때 주의해야 할 것은 베이스코이다.bject 특별반의 슈퍼클래스는 클래스반이라고 합니다.목요일에 했어요.즉, 모든 학급(Class류의 실례)은 방법 탐색 과정에서 반드시 Class류와 Module류를 통과해야 하며, 결과는 전체 클래스에서self를 명시하지 않고 키워드처럼 Class류와 Module류의 실례 방법을 호출해야 한다.이것이 바로 유홍의 진면목이다.Class클래스와Module클래스에 이어 Object클래스,BasicObject클래스가 마지막입니다. 이것은 전체 클래스뿐만 아니라 클래스 실례 대상을 포함한 모든 대상도 검색하기 때문에 클래스 매크로로서는 hogehoge입니다.
방법: "멈췄어"
5. 갈고리 방법을 사용하라!
길권: "학급홍을 완성한 건 좋은데 이러면 모든 학급이 불러내겠지."
거북이: "그러지 마! 한정된 대상과 일치하기를 바랄 뿐이야(include 이후)!"
두루미: "거북이가 좀 어색한 속박벽이 있는 것 같아."
거북이'이런 거북이를 위해 대상 모델에 다양한 변화가 있다(계승,include,extend)등 이벤트를 처리할 때 특정 처리의 연결 방법을 설정할 수 있다.이렇게 하면 각종 제한과 특수 처리를 설정할 수 있다.최저한도."included의 사용 방법을 이해하기만 하면 다음 문제에 직면할 수 있습니다."
Q4. MyModule을 만듭니다. 반에서include를 진행할 때 분류 방법을 사용할 수 있습니다
Class Intern
include MyModule
add_attr_with_date :shimatomo
end
obj = Intern.new
obj.shimatomo = 'shimada'
obj.shimatomo[:val] # => 'shimada'
obj.shimatomo[:created_at] # => Timeオブジェクト
A4. module MyModule
def self.included(klass)
class << klass
def add_attr_with_date(attr_name)
self.class_eval do
define_method "#{attr_name}=" do |value|
instance_variable_set("@#{attr_name}", { val: value, created_at: Time.now })
end
define_method "#{attr_name}" do
instance_variable_get("@#{attr_name}")
end
end
end
end
end
end
거북이: "self.included
방법에서 단순히 방법을 정의하면 실례적인 방법으로만 사용할 수 있지만 class << klass
부분에서klass의 특이류를 열고 방법을 정의하여 유홍을 실현하였습니다!"알겠습니다. "이 고리 방법의 사용 방법도 실제로 삐베 코드에 나타날 수 있으니 기억하는 것이 좋습니다."
지자: "이렇게 되면 금요일도 끝나고, 아주 긴 원 프로의 요일도 끝나. 그럼 너도 루비이스트지!"
Reference
이 문제에 관하여(재미있는 메타프로그래밍/6장), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/shimatomo/items/a214d05c61f6efbcef75텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)