2009-07-08 5 views
7

그래서 #new 메소드가 없기 때문에 Fixnum, Float 또는 Integer를 직접 서브 클래 싱하지 않아야한다는 것을 알고 있습니다. DelegateClass를 사용하는 것이 효과가있는 것처럼 보이지만 가장 좋은 방법입니까? 누구나 # 몇 가지 이유가 무엇인지 알지 못합니까?하위 클래스의 루비에서 Fixnum

은 내가 Fixnum이라는처럼 동작하지만, 몇 가지 추가 방법을 가지고 수업을해야하고, 내가 예를 들어, 클래스 내에서 self을 통해 값을 참조 할 수 있도록하고 싶습니다 :

class Foo < Fixnum 
    def initialize value 
    super value 
    end 

    def increment 
    self + 1 
    end 
end 

Foo.new(5).increment + 4 # => 10 
+0

정말로하고 싶은 것을 알려주십시오 (최종 목표). Google에서 최선의 방법을 알려 드리겠습니다. 나는 여기서 하위 분류가 적절하다고 생각하지 않는다. –

+0

이 질문을 업데이트했습니다. – cloudhead

답변

17
당신은 아주 쉽게 빠른 전달 구현을 직접 설정할 수 있습니다

:

다음
class MyNum 
    def initialize(number) 
    @number = number 
    end 

    def method_missing(name, *args, &blk) 
    ret = @number.send(name, *args, &blk) 
    ret.is_a?(Numeric) ? MyNum.new(ret) : ret 
    end 
end 

당신이 myNum에에 원하는 방법을 추가 할 수 있지만 그 방법에 @number에서 작동보다는해야합니다 슈퍼를 직접 호출 할 수 있습니다.

+0

흠. 그러나 MyNum.new (2) + MyNum.new (3)를 수행했다면 MyNum 인스턴스 대신 FixNum을 다시 얻지 않겠습니까? 당신이 MyNum.new에서 @ number.send를 감쌀 필요가 있다고 생각합니다. –

+0

원래 응답이 Numeric 인 경우 MyNum을 반환하도록 내 대답을 업데이트했습니다. –

+0

MyNum.new (5) == 5 AND 5 == MyNum.new (5)와 같이 MyNum을 구현할 수 있습니까? – rcrogers

2

FixNum 자체를 확장 할 수 있습니까? 처럼 ... 단어의 낮은 비트의 일부를 사용하여

class Fixnum 
    def even? 
    self % 2 == 0 
    end 
end 

42.even? 
+1

내가 할 수는 있지만, 나는하지 않을 것이다. 또한 Fixnum에는 #new가 없으므로 # 초기화에 기능을 추가 할 수 있어야합니다. – cloudhead

+1

원숭이 패치는 신중하게 사용해야합니다. 특정 유즈 케이스 만 루비 코어 클래스를 오염 시키려면 위험 할 수 있습니다. –

4

IIRC, 즉시 값으로 루비 저장 Fixnums의 주요 구현은 Fixnum이라는 대신 힙의 개체에 대한 포인터로 태그합니다. 그래서 32 비트 시스템에서 Fixnum은 전체 단어 대신 29 비트 (또는 그게 무엇이든)입니다.

그렇기 때문에 Fixnum의 단일 "인스턴스"에 메소드를 추가 할 수 없으며 서브 클래스를 작성할 수 없습니다.

"Fixnum-like"클래스를 사용하지 못하게되면 Fixnum 인스턴스 변수가있는 클래스를 만들어야하고 메서드 호출을 적절하게 전달해야합니다.

+0

아. 알겠습니다. 내가 서브 클래 싱 할 수있는 다른 클래스가 있습니까? Numeric은 #new를 가지고 있지만, 어떤 인자도 취하지 않으므로 추상 클래스라고 생각합니다. – cloudhead

+0

흠. 잠시 동안 Ruby를 접한 적이 없으며 숫자 클래스 트리가 배치 된 방식을 정확히 기억하지 않습니다. –

+0

유일한 확실한 후보는 BigDecimal입니다. –

관련 문제