2016-05-14 4 views
3

Ich möchte ein Objekt in Ruby erstellen, die etwas Code ausführen kann, wenn darauf zugegriffen wird, z. wenn es inspiziert oder verglichen wird. Es ist einfach genug, Nachrichten mit method_missing abzufangen (was object > 5 behandelt), aber dies deckt nicht alle Versuche ab, auf das Objekt zuzugreifen.Wie erkennt man, wenn ein Ruby-Objekt die rechte Seite eines Vergleichs ist?

Zur Veranschaulichung:

class Proxy 
    def initialize(obj) 
    @object = obj 
    end 

    def do_something 
    self 
    end 

    def do_something_else 
    self 
    end 

    def method_missing(msg, *args) 
    puts "I'm here #{msg}" 
    # Do something here 
    @object.send(msg, *args) 
    end 
end 

Verbrauch:

proxy = Proxy.new(5) 
proxy.do_something.do_something_else 

proxy > 2 
# I'm here > 
# true 

2 > proxy 
# ArgumentError: comparison of Fixnum with Proxy failed 

Ich frage mich, ob es 5 tatsächlich eine Implementierung von Proxy so dass 2 ist anstelle des Objekts sieht.

+0

Der Titel und der erste Satz Ihrer Frage stimmen nicht mit dem letzten Satz Ihrer Frage überein. Fragen Sie, wie Sie "etwas Code ausführen können, wenn auf [ein Objekt] zugegriffen wird", oder fragen Sie, wie man ein Proxy-Objekt auf der rechten Seite eines Vergleichsausdrucks mit einem Fixnum verwendet? Ich habe Probleme zu verstehen, wie diese beiden sehr unterschiedlichen Probleme zusammenhängen. –

+0

Sind sie sehr unterschiedlich? Ist Letzteres nicht nur ein Beispiel für Ersteres? – c4am95

+0

Nicht in irgendeiner Weise, die ich sehen kann. Dies scheint ein [XY-Problem] (http://xyproblem.info/) zu sein. Welches Problem versuchen Sie eigentlich zu lösen? Wenn ein Objekt "beim Zugriff auf einen Code" nur mühsam ausgeführt wird, ist dies nicht Teil der Lösung, das Objekt auf der rechten Seite eines Vergleichs mit einem Fixnum zu verwenden. –

Antwort

1

Nein, Sie können nicht erkennen, wenn ein Ruby-Objekt die rechte Seite eines Vergleichs ist. Ich werde daraus schließen, hoffentlich richtig, dass das Problem, Sie sind eigentlich versucht zu lösen ist, wie ein Ruby-Objekt auf der rechten Seite eines Vergleichs mit einem Objekt eines anderen Typs zu verwenden.

Die Antwort ist, eine coerce Methode zu definieren. Diese Methode wird automatisch aufgerufen, wenn sich das Objekt auf der rechten Seite eines Vergleichsoperators und ein "inkompatibles" Objekt auf der linken Seite befindet. Das LHS-Objekt wird als ein Argument geliefert, und es wird erwartet, dass ein Array mit zwei Elementen zurückgegeben wird: "Neue" LHS- und RHS-Werte, die sind kompatibel. Mit Ihrem Proxy Beispiel:

class Proxy 
    def initialize(obj) 
    @object = obj 
    end 

    def coerce(other) 
    if other.is_a?(Fixnum) 
     return [ other, @object.to_i ] 
    end 
    super 
    end 
end 

proxy = Proxy.new(5) 

2 > proxy 
# => false 

Natürlich wird Ihre coerce Methode wahrscheinlich komplexe, wenn Sie Ihre Proxy-Klasse wollen in der Lage sein, andere Werte als Fixnums „wrap“. Was tun Sie zum Beispiel, wenn @object ein String ist und other ein Float ist?

Und natürlich behandelt dies nur, wenn das Objekt der RHS ist. Damit es auch als LHS funktioniert, sollten Sie das Comparable Mixin verwenden.

+0

Du hattest recht ... das hat mir nicht geholfen X zu lösen. Aber ich schätze die Anleitung. Ich kann damit zumindest die häufigsten Anwendungsfälle behandeln. – c4am95

+0

Gibt es einen sicheren Weg, dies mit '==' zu erreichen? – c4am95

+0

Auf der LHS überschreiben Sie die Methode '==' ('def == (other) ...'). Ich glaube nicht, dass es einen Weg gibt, es auf der RHS a la 'coerce' zu ​​tun, aber ich könnte mich irren. Vielleicht könntest du etwas mit 'Module # predede' auf BasicObject machen? –

Verwandte Themen