eigenclass가 너무 비슷해 보이지만 self.class와 동등하지 않은 이유는 무엇입니까?


83

어딘가에서 메모를 놓쳤습니다. 이에 대해 설명해 주시기 바랍니다.

객체의 고유 클래스가 다른 이유는 무엇 self.class입니까?

class Foo
  def initialize(symbol)
    eigenclass = class << self
      self
    end
    eigenclass.class_eval do
      attr_accessor symbol
    end
  end
end

고유 클래스를 동일시하는 논리 열차 class.self는 다소 간단합니다.

class << self인스턴스 메서드가 아닌 클래스 메서드를 선언하는 방법입니다. 에 대한 바로 가기 def Foo.bar입니다.

따라서 클래스 객체에 대한 참조 내에서 반환 selfself.class. 이는 클래스 메서드 / 속성의 정의 를 위해로 class << self설정 되기 때문 입니다 .selfFoo.class

그냥 헷갈 리나요? 아니면 이것은 루비 메타 프로그래밍의 교활한 속임수입니까?

답변:


122

class << self클래스 메서드를 선언하는 방법 이상입니다 (그렇게 사용할 수는 있지만). 아마도 다음과 같은 사용법을 보셨을 것입니다.

class Foo
  class << self
    def a
      print "I could also have been defined as def Foo.a."
    end
  end
end

이것은 작동하고와 동일 def Foo.a하지만 작동 방식은 약간 미묘합니다. 비밀은 해당 self컨텍스트에서는 Foo클래스가의 고유 한 익명 하위 클래스 인 객체를 참조한다는 것 입니다 Class. 이 서브 클래스를 Foo's eigenclass 라고 합니다. 따라서 일반 메서드 호출 구문으로 액세스 할 수있는의 고유 클래스 에서 def a호출되는 새 메서드를 만듭니다 ..aFooFoo.a

이제 다른 예를 살펴 보겠습니다.

str = "abc"
other_str = "def"

class << str
  def frob
    return self + "d"
  end
end

print str.frob # => "abcd"
print other_str.frob # => raises an exception, 'frob' is not defined on other_str

이 예제는 처음에는 말하기 어려울 수 있지만 마지막 예제와 동일합니다. frob하지에 정의 된 String클래스 만의 eigenclass에 str고유 한 익명의 하위 클래스 String. 그래서 strfrob방법을, 그러나의 경우 String일반적으로하지 않습니다. 또한 String 메서드를 재정의 할 수 있습니다 (특정 까다로운 테스트 시나리오에서 매우 유용함).

이제 우리는 당신의 원래 예를 이해할 준비가되었습니다. Foo의 initialize 메서드 내부 self는 클래스 Foo가 아니라의 특정 인스턴스 를 참조 Foo합니다. 고유 클래스는의 하위 클래스 Foo이지만 그렇지 않습니다 Foo. 그렇지 않으면 두 번째 예제에서 본 트릭이 작동하지 않습니다. 따라서 예를 계속하려면 다음을 수행하십시오.

f1 = Foo.new(:weasels)
f2 = Foo.new(:monkeys)

f1.weasels = 4 # Fine
f2.monkeys = 5 # Also ok
print(f1.monkeys) # Doesn't work, f1 doesn't have a 'monkeys' method.

도움이 되었기를 바랍니다.


그렇다면 각 인스턴스는 생성 된 클래스의 익명 하위 클래스입니까?
Robert K

21
각 인스턴스의 클래스 는 생성 된 클래스의 익명 하위 클래스입니다. f1의 클래스는 Foo의 익명 하위 클래스이고 Foo의 클래스는 Class의 익명 하위 클래스입니다.
David Seiler

6
좋은 대답 :) 많은 사람들이 이것을 당신처럼 명확하게 이해하지 못합니다.
horseyguy

3
f1의 고유 클래스는 개념적으로 f1의 실제 인스턴스와 어떻게 다른가요? f1이 고유 클래스의 메서드에 액세스 할 수있는 유일한 인스턴스 인 경우 f1과 고유 클래스 간의 구분이 무너지지 않습니까?
elju 2013-09-29

1
@elju 그래, 좀. 정말 중요한 차이점은 "Foo"와 "f1의 고유 클래스"입니다. 그걸 가지고 있다면 아마 괜찮을 것입니다.
데이비드 세일러

46

가장 간단한 대답은 고유 클래스를 인스턴스화 할 수 없다는 것입니다.

class F
 def eigen
  class << self 
   self
  end
 end
end
F.new.eigen.new #=> TypeError: can't create instance of virtual class

당신은이 웹 사이트에 1 점만있을 수 있지만 당신과 당신의 스타일을 좋아합니다.
horseyguy 2010

난간에 동의합니다. 이것은 좋은 대답이다
크리스토퍼 스콧

3
이것은 매우 통찰력 있고 유용한 의견입니다. IFF는 이미 위의 @DavidSeiler의 답변을 읽었습니다.
Jazz

여기서 Theo 힘은 발생한 예외를 시연하고 있습니다.
New Alexandria

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.