2009-07-08 24 views
7

Vì vậy, tôi hiểu rằng bạn không được phép trực tiếp phân lớp Fixnum, Float hoặc Integer, vì chúng không có phương thứC# mới. Sử dụng DelegateClass dường như làm việc mặc dù, nhưng nó là cách tốt nhất? Bất cứ ai biết lý do đằng sau những lớp học này không có #new là gì?Phân lớp Fixnum trong ruby ​​

Tôi cần một lớp học mà cư xử như một Fixnum, nhưng có một số phương thức bổ sung, và tôi muốn để có thể tham khảo giá trị của nó thông qua self từ bên trong lớp, ví dụ:

class Foo < Fixnum 
    def initialize value 
    super value 
    end 

    def increment 
    self + 1 
    end 
end 

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

Hãy cho chúng tôi biết bạn đang thực sự cố gắng làm gì (mục tiêu cuối cùng) và chúng tôi sẽ cố gắng cho bạn biết cách tốt nhất để làm điều đó. Tôi không nghĩ rằng phân lớp là thích hợp ở đây. –

+0

đã cập nhật câu hỏi. – cloudhead

Trả lời

17

Bạn có thể khá dễ dàng thiết lập một chuyển tiếp thực hiện nhanh chóng tự hỏi:

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 

Sau đó, bạn có thể thêm bất cứ điều gì phương pháp bạn muốn trên MyNum, nhưng bạn sẽ cần để hoạt động trên @number trong những phương pháp, chứ không phải là có thể gọi siêu trực tiếp.

+0

Hmm. Nhưng nếu bạn đã làm MyNum.new (2) + MyNum.new (3), bạn sẽ không nhận được một Fixnum trở lại thay vì một trường hợp MyNum? Tôi nghĩ rằng bạn cần phải bọc @ number.send trong MyNum.new –

+0

Tôi đã cập nhật câu trả lời của mình để đảm bảo rằng bạn trả về MyNum nếu câu trả lời ban đầu là Số. –

+0

MyNum có thể được thực hiện sao cho MyNum.new (5) == 5 AND 5 == MyNum.new (5)? – rcrogers

2

Bạn không thể tự mở rộng FixNum? Giống như ...

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

42.even? 
+1

Tôi có thể, nhưng tôi không muốn. Ngoài ra, Fixnum không có #new, và tôi cần để có thể thêm chức năng để #initialize. – cloudhead

+1

Khỉ vá nên được sử dụng cẩn thận. Để gây ô nhiễm một lớp lõi Ruby chỉ cho một trường hợp sử dụng cụ thể, có thể nguy hiểm. –

4

IIRC, việc thực hiện chính của Ruby cửa hàng Fixnums như các giá trị tức thời, sử dụng một số các bit thấp của từ để gắn thẻ nó như là một Fixnum thay vì một con trỏ đến một đối tượng trên heap. Đó là lý do tại sao, trên một máy 32 bit, Fixnums chỉ có 29 bit (hoặc bất kể nó là gì) thay vì một từ đầy đủ.

Vì vậy, do đó, bạn không thể thêm phương thức vào một "cá thể" duy nhất của Fixnum và bạn không thể phân lớp nó.

Nếu bạn đã chết khi có lớp "Fixnum-like", có thể bạn sẽ phải tạo một lớp có biến thể hiện Fixnum và các cuộc gọi phương thức chuyển tiếp thích hợp.

+0

Tôi hiểu rồi. Có lớp nào khác tôi có thể phân lớp? Số có một #new, nhưng nó không có bất kỳ đối số, vì vậy tôi cho rằng đó là một lớp trừu tượng. – cloudhead

+0

Hmm. Tôi đã không chạm vào Ruby trong một thời gian, và tôi không nhớ chính xác cách cây lớp số được đặt ra. –

+0

Ứng viên duy nhất rõ ràng là BigDecimal. –

Các vấn đề liên quan