Frage

In Ruby-Objekte haben eine praktische Methode namens method_missing, die ein bis Griff Methodenaufrufe für Methoden ermöglicht, die nicht einmal waren (explizit) definiert:

  

Ausgeführt von Ruby, wenn obj eine Nachricht gesendet wird, nicht damit umgehen kann. Symbol ist das Symbol für die Verfahren genannt, und args irgendwelche Argumente, die an sie übergeben wurden. Standardmäßig wirft der Interpreter einen Fehler, wenn diese Methode aufgerufen wird. Allerdings ist es möglich, die Methode zu überschreiben dynamischere Verhalten zu schaffen. Das folgende Beispiel erzeugt eine Klasse Roman, der anspricht, auf Verfahren mit den Namen der römischen Ziffern besteht, die entsprechende ganzzahlige Werte zurückkehrt.

class Roman
 def romanToInt(str)
   # ...
 end
 def method_missing(methId)
   str = methId.id2name
   romanToInt(str)
 end
end

r = Roman.new
r.iv      #=> 4
r.xxiii   #=> 23
r.mm      #=> 2000

Zum Beispiel, Ruby on Rails verwendet diese Aufrufe von Methoden zu ermöglichen, wie find_by_my_column_name.

Meine Frage ist, was andere Sprachen unterstützen ein Äquivalent zu method_missing und wie implementieren Sie das Äquivalent in Ihrem Code?

War es hilfreich?

Lösung

Einige Anwendungsfälle von method_missing können in Python implementiert werden __getattr__ z.

class Roman(object):
  def roman_to_int(self, roman):
    # implementation here

  def __getattr__(self, name):
    return self.roman_to_int(name)

Dann können Sie tun:

>>> r = Roman()
>>> r.iv
4

Andere Tipps

Smalltalk hat die doesNotUnderstand Nachricht, die wahrscheinlich die ursprüngliche Umsetzung dieser Idee ist, da Smalltalk eine von Rubys Eltern ist. Die Default-Implementierung zeigt ein Fehlerfenster, aber es kann etwas zu tun interessanter außer Kraft gesetzt werden.

PHP-Objekte können mit der __call spezielle Methode

Zum Beispiel:

<?php
class MethodTest {
    public function __call($name, $arguments) {
        // Note: value of $name is case sensitive.
        echo "Calling object method '$name' "
             . implode(', ', $arguments). "\n";
    }
}

$obj = new MethodTest;
$obj->runTest('in object context');
?>

JavaScript hat noSuchMethod , aber leider ist dies nur durch Firefox / Spider unterstützt.

Hier ist ein Beispiel:

wittyProjectName.__noSuchMethod__ = function __noSuchMethod__ (id, args) {
   if (id == 'errorize') {
    wittyProjectName.log("wittyProjectName.errorize has been deprecated.\n" +
                         "Use wittyProjectName.log(message, " +
                         "wittyProjectName.LOGTYPE_ERROR) instead.",
                         this.LOGTYPE_LOG);
    // just act as a wrapper for the newer log method
    args.push(this.LOGTYPE_ERROR);
    this.log.apply(this, args);
  }
}

Perl hat AUTOLOAD , die auf Subroutinen & Klassenarbeiten / Objektmethoden.

Unterprogramm Beispiel:

use 5.012;
use warnings;

sub AUTOLOAD {
    my $sub_missing = our $AUTOLOAD;
    $sub_missing =~ s/.*:://;
    uc $sub_missing;
}

say foo();   # => FOO

Klasse / Objektmethodenaufruf Beispiel:

use 5.012;
use warnings;

{
    package Shout;

    sub new { bless {}, shift }

    sub AUTOLOAD {
        my $method_missing = our $AUTOLOAD;
        $method_missing =~ s/.*:://;
        uc $method_missing;
    }
}

say Shout->bar;         # => BAR

my $shout = Shout->new;
say $shout->baz;        # => BAZ

Objective-C unterstützt das Gleiche und es nennt Forwarding .

Dies ist in Lua erreicht, indem der __index Schlüssel eines Metatabelle .

t = {}
meta = {__index = function(_, idx) return function() print(idx) end end}
setmetatable(t, meta)

t.foo()
t.bar()

Dieser Code wird ausgegeben:

foo
bar

Ich war vor für diese suchen, und fand eine

In Common Lisp, no-applicable-method kann für diesen Zweck verwendet werden, gemäß dem Common Lisp Hyper Spec :

  

Die generische Funktion nicht anwendbar-Methode wird aufgerufen, wenn eine generische Funktion aufgerufen wird und keine Methode für die generische Funktion anwendbar ist. Die Standardmethode meldet einen Fehler.

     

Die generische Funktion nicht anwendbar-Methode ist nicht für Programmierer aufgerufen werden. Programmierer können Methoden schreiben für sie.

So zum Beispiel:

(defmethod no-applicable-method (gf &rest args)
  ;(error "No applicable method for args:~% ~s~% to ~s" args gf)
  (%error (make-condition 'no-applicable-method :generic-function gf :arguments args) '()
        ;; Go past the anonymous frame to the frame for the caller of the generic function
        (parent-frame (%get-frame-ptr))))

C # hat jetzt TryInvokeMember , für dynamische Objekte (abgeleitet von Dynamic )

Actionscript 3.0 verfügt über eine Proxy Klasse, die diese Funktionalität bereitzustellen erweitert werden kann.

dynamic class MyProxy extends Proxy {
  flash_proxy override function callProperty(name:*, ...rest):* {
    try {
      // custom code here
    }
    catch (e:Error) {
      // respond to error here
    }
}  

Tcl hat etwas ähnliches. Jedes Mal, wenn Sie einen Befehl aufrufen, die nicht gefunden werden, wird das Verfahren unbekannt wird aufgerufen. Zwar ist es nicht etwas, das Sie normalerweise benutzen, kann es manchmal nützlich sein.

In CFML (Coldfusion, Railo, OpenBD), der onMissingMethod() Ereignishandler innerhalb einer Komponente definiert ist, wird auf diese Komponente nicht definierte Methode Anrufe empfangen. Die Argumente missingMethodName und missingMethodArguments werden automatisch eingeleitet, dynamisches Handling des fehlenden Methodenaufruf ermöglicht. Dies ist der Mechanismus, der die Erstellung von impliziten Setter / Getter Schemata erleichtert, bevor sie begann, in die verschiedenen CFML Motoren gebaut werden.

Sein Pendant in Io wird die forward Methode.

Aus der Dokumentation:

  

Wenn ein Objekt nicht reagiert auf eine Nachricht, wird sie ihre „vorwärts“ Methode aufrufen, wenn sie eine hat ....

Hier ist ein einfaches Beispiel:

Shout := Object clone do (
    forward := method (
        method_missing := call message name
        method_missing asUppercase
    )
)

Shout baz println     # => BAZ

/ I3az /

Boo hat IQuackFu - gibt es bereits eine ausgezeichnete Zusammenfassung auf SO unter

scroll top