2013-12-18 3 views
6

ich von leicht erben kann, sagen wir, String zum Beispiel wie folgt aus:Wie kann ich von Rational (oder einer Klasse ohne Konstruktor) erben?

class MyString < String 
    def stuff 
    self + ' and stuff' 
    end 
end 

# This works: 
MyString.new('things').stuff # => 'things and stuff' 

Aber wie kann ich erben von Rational, die keinen Konstruktor hat? Zum Beispiel:

def MyRat < Rational 
    def inc 
    self + 1 
    end 
end 

# I have tried to initialize like this: 
MyRat.new(10).inC# => NoMethodError: undefined method `new' for MyRat:Class 
MyRat(10).inC# => NoMethodError: undefined method `MyRat' for main:Object 
MyRat.send(:initialize, 10).inc # => TypeError: already initialized class 
# ??? 
# None of it works! 

Ich kann keinen Weg finden, meine neue Klasse zu initialisieren.

+0

Warum schreiben Sie nicht Ihre eigene '# initialize' Methode? –

+0

@ArupRakshit kann ich nicht. Wie würde ich das tun? – Doorknob

Antwort

5

Sie können Ihr eigenes Objekt als Proxy um Rational definieren.

class MyRat < BasicObject 
    def initialize(value) 
    @rational = Rational(value) 
    end 

    def inc 
    @rational + 1 
    end 

    def method_missing(name, *args, &block) 
    @rational.send(name, *args, &block) 
    end 
end 

In Ihrer Klasse definierte Methoden werden verwendet, andernfalls delegiert die Klasse an die rationale Instanz.

r = MyRat.new(10) 

# MyRat#inc is used 
r.inc 
# => (11/1) 

# to_int delegates to Rational 
r.to_int 
# => 10 

Eine teilweise Erklärung, weil bezifferbar initialize hat, ist in this thread

am C-Code Sehen, ich sehe, dass neue() in Numeric existiert und Float, aber es ist speziell entfernt : rb_cInteger = rb_define_class ("Ganzzahl", rb_cNumeric); rb_undef_alloc_func (rb_cInteger); rb_undef_method (CLASS_OF (rb_cInteger), "neu");

#....and for floats.. 
rb_undef_alloc_func(rb_cFloat); 
rb_undef_method(CLASS_OF(rb_cFloat), "new"); 

Der Ruby-Quellcode enthält keine Erklärung für die Entfernung von neuen. Deshalb frage ich mich, was der Grund dafür war. Es scheint nicht zu sein, technische Einschränkung in der Ruby-Interpreter. Momentan macht es mir wenig Sinn.

und der Grund ist, weil

Es ist eine interne Optimierung. Fixnums müssen nicht erstellt werden und sie müssen nie GC'ed sein. Das macht einen langen Weg, um Mathe schneller zu machen als mit gewöhnlichen Objekten (zumindest für Fixnums).

Zusätzliche Vorschläge und Alternativen werden in diesem Artikel The Complete Numeric Class erläutert.

+0

Das sollte funktionieren, aber ich bin ziemlich neugierig, warum Sie nicht von "Rational" erben können. –

+0

Danke, ich versuche das gerade jetzt ... – Doorknob

+0

Sie müssen alle Methoden aufheben ['BasicObject'] (http://www.ruby-doc.org/core-2.0.0/BasicObject.html) bietet: 'eql?' und '==' und '! =' –

Verwandte Themen