루비의 클래스 메소드는 사실상 싱글톤 메소드입니다.
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)
바로 상수를 보는 visibility가 다르게 되는 거죠.
Comments 6
모든 클래스 메소드가 싱클톤 메소드는 아닌 것 같습니다.
다음의 예처럼 Class class에 정의된 인스턴스 메소드는 다른 클래스의 클래스 메소드가 됩니다.
class C
end
class Class
def test
puts “Class#test”
end
end
p C.singleton_methods #=>[]
Posted 05 Mar 2006 at 1:05 pm ¶C.test #=>”Class#test”
singleton_methods는 메소드 리스트를 얻는데 아주 간단한 테스트만 합니다. 주어진 오브젝트 (메소드 리시버)의 클래스로부터 시작해서 그 클래스가 싱글톤 클래스냐? 그러면 거기 정의된 메소드들을 싱글톤 메소드 리스트에 포함시킵니다. singleton_methods의 아규먼트가 true거나 없으면 클래스의 수퍼들을 따라 올라가면서 같은 일을 반복합니다.
싱글톤 클래스라는 플래그는 class << obj 처럼 explicit하게 정의되는 경우, def Symbol.method 처럼 어떤 심볼에 메소드가 추가되려 할 때 메타클래스를 자동으로 만드는 경우 등에 해당 메타클래스에 세팅됩니다. 따라서 일반적으로 “모든 메타클래스에 정의된 메소드는 싱글톤 메소드이다”라는 말은 성립할 것 같습니다. Class 클래스에서 정의된 인스턴스 메소드는 inheritance에 의해 C에서 visible하기는 한데, 그것을 C의 클래스 메소드로 봐야 할지는 잘 모르겠네요. 형태적으로 보면 C.test가 성립하니 그럴 것도 같고…
결론적으로 “모든 클래스 메소드는 싱글톤 메소드다”라는 명제는 “클래스 메소드”가 뭐냐라고 보는 것에 따라 참이기도 하고 거짓이기도 할 것 같습니다.
Posted 05 Mar 2006 at 5:48 pm ¶무책님;;; 이런건 소스 다 열어보고 아시는건가요??
Posted 06 Mar 2006 at 1:21 am ¶어떻게 그런 세세한걸 다 알고 계시는거죠-_-;;;
^^ 예전에 Undocumented DOS라는 책에서 Andrew Schulman이 그랬죠, “Use the source, Luke!”
Posted 06 Mar 2006 at 7:52 am ¶무책님께서 정확히 짚어 주셨네요.
사실 저는 (좀 무료해서…) 약간의 예외적인 경우를 지적하고 싶었던 것이었습니다…;-)
“클래스 메소드는 이거다”라고 정의해 주는 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
좀 억지스러운가요? ㅋㅋ
Posted 06 Mar 2006 at 9:04 am ¶사실 루비에서는 클래스와 객체로 나누는 것보다 객체와 싱글톤 객체로만 나누는 것이 더 맞을 것 같습니다.
그래서 제 생각에 루비는 prototype-based OO와 class- based OO의 중간에 해당하는 언어라고 생각합니다.
모든 게 객체이지만 클래스의 개념이 있는 언어라고나 할까요…
공성식님 말씀이 제가 생각했던 거랑 같은데요..
바로, p (C.methods – C.instance_methods).include?(”test”) #=>true 이거죠 ㅎㅎ
그런데, 아무리 찾아도 f= Foo.new 가 주어졌을 때, Foo로부터든 f로 부터든
class method 를 출력하기 위한 방법이 눈에 안띄더란 말이죠….
차라리 클래스메소드란 말이 없던가;; 그것도 아니면 클래스 메소드 목록을
Posted 06 Mar 2006 at 3:22 pm ¶보여줄 방법이 쉽던가 해야할텐데;; 클래스 메소드 목록보여주기란
단순한 동작을 하고 싶어도 어려워요; 별거 별거를 다 알아야하고..
Post a Comment