여기에 무슨 일이 일어나는지 설명하는 데 도움이되는 몇 가지 코드가 있습니다. 나는 약간의 설명을 추가 할 것이다. 여기
module Mappable
def self.included(klass)
puts "klass = #{klass}"
puts "self before class_eval = #{self}"
klass.class_eval do
puts "self after class_eval and before class << self = #{self}"
class << self
puts "self after class << self = #{self}"
attr_accessor :source
end
end
end
end
class A
include Mappable
attr_accessor :source
@source = 'cat'
def initialize
@source = 'dog'
end
end
은
Mappable
가
A
에
include
D되는 결과 :
#-> klass = A
#-> self before class_eval = Mappable
#-> self after class_eval and before class << self = A
#-> self after class << self = #<Class:A>
이 klass.class_eval
(A.class_eval
)은 Mappable
에서 A
하는 문맥 (self
의 값)을 변경하는 것을 알 수있다. class << self
(class << A
) 그러면 A
의 싱글 톤 클래스로 컨텍스트가 변경됩니다.이 메서드는 attr_accessor
메서드를 실행하여 클래스 인스턴스 변수 @source
에 대한 읽기/쓰기 접근자를 만듭니다.
A.methods(false)
#=> [:source, :source=]
A.instance_variables
#=> [:@source]
A.source
#=> "cat"
A.source = 'pig'
A.source
#=> "pig"
이것은 우리가 @a
변수 클래스 인스턴스 생성 한 접근이 제대로 작동 것으로 보인다 보여줍니다. 이제 인스턴스 메소드와 인스턴스 변수를 살펴 보겠습니다.
A.instance_methods(false)
#=> [:source, :source=]
a = A.new
#=> #<A:0x000001018fdc78 @source="dog">
a.instance_variables
#=> [:@source]
a.source
#=> "dog"
a.source = 'cow'
#=> "cow"
a.source
#=> "cow"
괜찮은 것 같습니다. A
및 a
에는 각각 인스턴스 변수 @source
이 있지만 두 변수는 관련이 없다는 것을 이해하는 것이 중요합니다. 마지막으로, 우리는 클래스 인스턴스 변수의 값에 영향을 미치지 않았다의 인스턴스 변수의 값을 변경에 다음 사항을 확인하자 :
A.source
#=> "pig"
하기 위해, A
의 싱글 톤 클래스에 컨텍스트를 변경하는 다른 방법이 있습니다 메소드 attr_accessor
을 실행하십시오. 차라리 루비 1.9.2부터 우리와 함께하고있다 Object#singleton_class를 사용하는 발견 해요 :
def self.included(klass)
klass.singleton_class.class_eval do
attr_accessor :source
end
end
와우, 이런, 감사합니다! 업데이트를 기대하지만이 자체는 훌륭한 설명입니다. –