class method는 사실상 singleton method

Tags:

루비의 클래스 메소드는 사실상 싱글톤 메소드입니다.

irb(main):001:0> class Foo
irb(main):002:1>   def self.bar
irb(main):003:2>   end
irb(main):004:1> end
=> nil
irb(main):005:0> Foo.singleton_methods
=> ["bar"]
irb(main):006:0> Foo2 = Class.new
=> Foo2
irb(main):007:0> class << Foo2
irb(main):008:1>   def bar
irb(main):009:2>   end
irb(main):010:1> end
=> nil
irb(main):011:0> Foo2.singleton_methods
=> ["bar"]
irb(main):012:0>

그러나 여기에서 볼 수 있듯이, 둘간의 약간의 차이는 있습니다.

X = 1
class C
X = 2
def self.a
puts X
end
end

class << C def b puts X end end C.a # 2 (C::X) C.b # 1 (top-level X) [/code] 바로 상수를 보는 visibility가 다르게 되는 거죠.

Comments

6 responses to “class method는 사실상 singleton method”

  1. 공성식 Avatar

    모든 클래스 메소드가 싱클톤 메소드는 아닌 것 같습니다.
    다음의 예처럼 Class class에 정의된 인스턴스 메소드는 다른 클래스의 클래스 메소드가 됩니다.

    class C
    end

    class Class
    def test
    puts “Class#test”
    end
    end

    p C.singleton_methods #=>[]
    C.test #=>”Class#test”

  2. 무책 Avatar

    singleton_methods는 메소드 리스트를 얻는데 아주 간단한 테스트만 합니다. 주어진 오브젝트 (메소드 리시버)의 클래스로부터 시작해서 그 클래스가 싱글톤 클래스냐? 그러면 거기 정의된 메소드들을 싱글톤 메소드 리스트에 포함시킵니다. singleton_methods의 아규먼트가 true거나 없으면 클래스의 수퍼들을 따라 올라가면서 같은 일을 반복합니다.

    싱글톤 클래스라는 플래그는 class << obj 처럼 explicit하게 정의되는 경우, def Symbol.method 처럼 어떤 심볼에 메소드가 추가되려 할 때 메타클래스를 자동으로 만드는 경우 등에 해당 메타클래스에 세팅됩니다. 따라서 일반적으로 “모든 메타클래스에 정의된 메소드는 싱글톤 메소드이다”라는 말은 성립할 것 같습니다. Class 클래스에서 정의된 인스턴스 메소드는 inheritance에 의해 C에서 visible하기는 한데, 그것을 C의 클래스 메소드로 봐야 할지는 잘 모르겠네요. 형태적으로 보면 C.test가 성립하니 그럴 것도 같고…

    결론적으로 “모든 클래스 메소드는 싱글톤 메소드다”라는 명제는 “클래스 메소드”가 뭐냐라고 보는 것에 따라 참이기도 하고 거짓이기도 할 것 같습니다.

  3. MKSeo Avatar
    MKSeo

    무책님;;; 이런건 소스 다 열어보고 아시는건가요??
    어떻게 그런 세세한걸 다 알고 계시는거죠-_-;;;

  4. 무책 Avatar

    ^^ 예전에 Undocumented DOS라는 책에서 Andrew Schulman이 그랬죠, “Use the source, Luke!”

  5. 공성식 Avatar

    무책님께서 정확히 짚어 주셨네요.
    사실 저는 (좀 무료해서…) 약간의 예외적인 경우를 지적하고 싶었던 것이었습니다…;-)

    “클래스 메소드는 이거다”라고 정의해 주는 Document를 찾지는 못하겠고 그냥 순수한 논리로만 따져보면 다음과 같습니다.
    모든 메소드는 클래스 메소드이거나 객체 메소드라고 볼 수 있겠죠?(exclusive OR)
    그럼 class C의 모든 메소드에서 객체 메소드들을 빼면 클래스 메소드만 남는 거죠?
    위의 가정을 기반으로 했을 때 C.test는 클래스 메소드가 됩니다.

    class C
    end

    class Class
    def test
    puts “Class#test”
    end
    end

    p (C.methods – C.instance_methods).include?(“test”) #=>true

    좀 억지스러운가요? ㅋㅋ
    사실 루비에서는 클래스와 객체로 나누는 것보다 객체와 싱글톤 객체로만 나누는 것이 더 맞을 것 같습니다.
    그래서 제 생각에 루비는 prototype-based OO와 class- based OO의 중간에 해당하는 언어라고 생각합니다.
    모든 게 객체이지만 클래스의 개념이 있는 언어라고나 할까요…

  6. MKSeo Avatar
    MKSeo

    공성식님 말씀이 제가 생각했던 거랑 같은데요..
    바로, p (C.methods – C.instance_methods).include?(”test”) #=>true 이거죠 ㅎㅎ

    그런데, 아무리 찾아도 f= Foo.new 가 주어졌을 때, Foo로부터든 f로 부터든
    class method 를 출력하기 위한 방법이 눈에 안띄더란 말이죠….

    차라리 클래스메소드란 말이 없던가;; 그것도 아니면 클래스 메소드 목록을
    보여줄 방법이 쉽던가 해야할텐데;; 클래스 메소드 목록보여주기란
    단순한 동작을 하고 싶어도 어려워요; 별거 별거를 다 알아야하고..

Leave a Reply

Your email address will not be published. Required fields are marked *