10
class << self 
attr_accessor :n, :totalX, :totalY 
end 

위의 구문은 클래스 인스턴스 변수를 정의하는 데 사용됩니다. 그러나 구문에서 의미하는 바가 무엇인지 생각하면 이해가되지 않으므로이 유형의 구문이 다른 유형의 정의에도 사용되는지 궁금합니다. 여기 혼란의 내 요점은 이것이다 :Ruby에는 다음과 같은 구문 관련 응용 프로그램이 있습니다. class << self ... end

class << self 

추가] 연산자는 일반적으로 "왼쪽에있는 객체에 대한 권리에 무엇이 추가"를 의미한다. 그러나이 블록의 맥락에서 "이 블록의 내용을 인스턴스가 아닌 클래스 인스턴스의 정의에 넣는"방법은 무엇입니까? 의

class Point 
    # Instance methods go here 
    class << self 
    # Class methods go here 
    end 
end 

답변

18

루비에서는 기존 클래스를 다시 열고 메소드를 추가 할 수 있습니다.

class Foo 
    def bob 
    return "hello from bob" 
    end 
end 

이러한 방법은 Class - 클래스의 바로 인스턴스가되는합니다 (Foo - 클래스의 내부 사전 (어쩌면 인스턴스 변수)에 어딘가에 저장되어 얻을 따라서 이있다 : 즉, 말할 수있다 인스턴스 변수)

그러나 의외 것은 당신이 또한 인스턴스에 메서드를 추가 할 수있다 기존 개체의

foo = Foo.new 
foo2 = Foo.new 

def foo.fred 
    return "I am fred" 
end 


foo.fred #=> "I am fred" 
foo2.fred #=> NoMethodError 

하지만 이 방법은 실제로 어디에 저장됩니까?

루비가 무대 뒤에서 새로운 클래스를 생성 밝혀 (때로는 싱글 톤 클래스, 메타 클래스라고 또는 eigenclass)Foo - 클래스와 해당 인스턴스 사이의 상속 계층 구조 에 삽입됩니다.

그래서 상속 관계는 다음과 같습니다

foo < (eigenclass of foo) < Foo < Class 

을 (당신이 foo는 말을합니다.수퍼 클래스에서는 싱글 톤 클래스가 표시되지 않음)

class << X -syntax는이 특수 클래스를 사용하여 직접 조작 할 수있는 방법입니다. 다음 코드 블록은 정확히 동일합니다

def foo.bar 
    return "xy" 
end 

# is exactly the same as 

class << foo 
    def bar 
    return "xy" 
    end 
end 

그래서 class Foo < Barclass << Foo 사이의 유사성은 우연하지 않다, 모두에서 진행 상속이 있습니다.

루비에서 기억해야 할 것은 "X의 메타 클래스를 열고"등 class << X

생각해 클래스 자체는 단지 객체이다. 그래서 만약 (클래스 Class의 인스턴스)를 사용하면 말 :

class Foo 
    class << self 
    def k 
     return "x" 
    end 
    end 
end 

(self이 코드 블록에 Foo에 바인딩) 때문에 k는 클래스 메소드 만드는 인스턴스 메소드 Foo의 eigenclass의입니다 '이 - Foo

(불행히도 다이어그램을 포함하지 않는 웹 버전)이이 chapter about classes of the Pickaxe에 더 명확하게 설명 모든

및 _whys Seeing Metaclasses Clearly

2

생각해 : 나는 다른에는 여기에 같은 클래스 변수를 만들 것 중에 하나의 맥락에서 클래스 < < 자체가 클래스 인스턴스 변수를 정의 할 수 있습니다 이유에 혼란 스러워요 같은 이유로

클래스는 모든 접근 자 및 인스턴스 변수를 포함하는 멤버 사전을 포함합니다. 클래스에 "추가"를 "자체"라고 말하면 클래스 멤버 사전에 추가하십시오.

나는 표기법을 조금씩 줄 것이다.

+0

확인을위한 보는 좋은 방법입니다. 실제로 수업은 사전입니다. 그러나 실제로 마지막 문장을 추가하기 전에 여러분은 답을 얻었습니다. 다른 문맥에서 같은 sytax (책에서 보았 듯이)는 클래스 인스턴스 메소드 대신 클래스 메소드를 생성합니다. 맨 아래에있는 Point 클래스 예제는 클래스 메소드를 생성하지만 맨 위에있는 attr_accessor는 클래스 - 인스턴스 레벨에있는 속성을 제공하는 이유는 무엇입니까? –

+0

실제로 당신이 제공 한 설명을 사용하여 어쩌면 나는 이전 주석에서 질문에 대답 할 수있다. attr_accessor 메소드는 Class 클래스의 instance_variable_set 및 instance_variable_get 메소드를 호출한다. 일반적으로 그것들은 인스턴스 변수를 생성하게 될 것입니다 만, 우리가 클래스 사전에 추가하기 때문에 클래스 인스턴스 변수를 생성하게됩니다. 좋아, 이제 알았어. 감사. –

+1

-1은 클래스 << x ... end가 실제로 x의 메타 클래스가 아닌 x의 메타 클래스에 정보를 추가하기 때문에 오도 된 것입니다. – rampion

1

실제로 "추가"연산자로 생각하면 혼란 스럽습니다. 그것을보기위한 더 좋은 방법은 class Foo이 Foo 클래스를 연다. 즉, 필요하다면 클래스 객체 Foo에 'self'를 설정하여 현재 'self'객체의 고유 클래스를 여는 것이다. 그것이 자기에 국한되지 않습니다 - 어떤 개체 막대에 대해, 당신은 그 객체의 고유 클래스를 열려면 클래스 < < 막대를 말할 수 있습니다.

class A 
    def hello 
    print "hello world" 
    end 
end 

a = A.new 
b = A.new 

class << a 
    def goodbye 
    print "goodbye cruel world" 
    end 
end 

a.hello 
b.hello 
a.goodbye 
b.goodbye