programming popular most languages examples programming-languages language-features method-missing

programming languages - popular - ¿Hay equivalentes al método de Ruby_missing en otros idiomas?



programming languages 2018 (15)

Actionscript 3.0 tiene una clase Proxy que puede extenderse para proporcionar esta funcionalidad.

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

En Ruby, los objetos tienen un método práctico llamado method_missing que permite manejar llamadas de método para métodos que ni siquiera se han definido (explícitamente):

Invocado por Ruby cuando a obj se le envía un mensaje que no puede manejar. símbolo es el símbolo para el método llamado y args son los argumentos que se le pasaron. De forma predeterminada, el intérprete genera un error cuando se llama a este método. Sin embargo, es posible anular el método para proporcionar un comportamiento más dinámico. El siguiente ejemplo crea una clase romana, que responde a los métodos con nombres que consisten en números romanos, devolviendo los valores enteros correspondientes.

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

Por ejemplo, Ruby on Rails usa esto para permitir llamadas a métodos como find_by_my_column_name .

Mi pregunta es, ¿qué otros idiomas admiten un equivalente a method_missing y cómo implementas el equivalente en tu código?


Algunos casos de uso de method_missing se pueden implementar en Python usando __getattr__ por ejemplo

class Roman(object): def roman_to_int(self, roman): # implementation here def __getattr__(self, name): return self.roman_to_int(name)

Entonces puedes hacer:

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


Boo tiene IQuackFu - ya hay un excelente resumen sobre SO en how-can-i-intercept-a-method-call-in-boo

Aquí hay un ejemplo:

class XmlObject(IQuackFu): _element as XmlElement def constructor(element as XmlElement): _element = element def QuackInvoke(name as string, args as (object)) as object: pass # ignored def QuackSet(name as string, parameters as (object), value) as object: pass # ignored def QuackGet(name as string, parameters as (object)) as object: elements = _element.SelectNodes(name) if elements is not null: return XmlObject(elements[0]) if elements.Count == 1 return XmlObject(e) for e as XmlElement in elements override def ToString(): return _element.InnerText



En CFML (ColdFusion, Railo, OpenBD), el controlador de eventos onMissingMethod() , definido dentro de un componente, recibirá llamadas a métodos no definidos en ese componente. Los argumentos missingMethodName y missingMethodArguments se pasan automáticamente, lo que permite el manejo dinámico de la llamada al método que falta. Este es el mecanismo que facilitó la creación de esquemas setter / getter implícitos antes de que comenzaran a integrarse en los diversos motores CFML.


En Common Lisp, el no-applicable-method puede usarse para este propósito, de acuerdo con la especificación Hyper Spec de Common Lisp :

La función genérica no-aplicable-método se llama cuando se invoca una función genérica y no se aplica ningún método en esa función genérica. El método predeterminado señala un error.

La función genérica no-aplicable-método no está destinada a ser llamada por los programadores. Los programadores pueden escribir métodos para ello.

Así por ejemplo:

(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))))


Estaba buscando esto antes, y encontré una lista útil (rápidamente superada aquí) como parte del proyecto Merd en SourceForge.

Construct Language ----------- ---------- AUTOLOAD Perl AUTOSCALAR, AUTOMETH, AUTOLOAD... Perl6 __getattr__ Python method_missing Ruby doesNotUnderstand Smalltalk __noSuchMethod__(17) CoffeeScript, JavaScript unknown Tcl no-applicable-method Common Lisp doesNotRecognizeSelector Objective-C TryInvokeMember(18) C# match [name, args] { ... } E the predicate fail Prolog forward Io

Con notas a pie de página:

  • (17) Firefox
  • (18) C # 4, solo para objetos "dinámicos"

Esto se logra en Lua configurando la clave __index de un metatable .

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

Este código dará salida:

foo bar


JavaScript no tiene noSuchMethod , pero desafortunadamente esto solo es compatible con Firefox / Spidermonkey.

Aquí hay un ejemplo:

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); } }


Los objetos PHP se pueden sobrecargar con el método especial __call .

Por ejemplo:

<?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''); ?>


Objective-C soporta lo mismo y lo llama forwarding .


Perl tiene AUTOLOAD que funciona en subrutinas y métodos de clase / objeto.

Ejemplo de subrutina:

use 5.012; use warnings; sub AUTOLOAD { my $sub_missing = our $AUTOLOAD; $sub_missing =~ s/.*:://; uc $sub_missing; } say foo(); # => FOO

Ejemplo de llamada al método clase / objeto:

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


Smalltalk tiene el mensaje doesNotUnderstand , que probablemente sea la implementación original de esta idea, dado que Smalltalk es uno de los padres de Ruby. La implementación predeterminada muestra una ventana de error, pero se puede anular para hacer algo más interesante.


Su equivalente en Io es usar el método forward .

De la documentación:

Si un objeto no responde a un mensaje, invocará su método de "reenvío" si tiene uno ...

Aquí hay un ejemplo simple:

Shout := Object clone do ( forward := method ( method_missing := call message name method_missing asUppercase ) ) Shout baz println # => BAZ

/ I3az /


Tcl tiene algo similar. Cada vez que llame a un comando que no se pueda encontrar, se llamará al procedimiento unknown . Si bien no es algo que se usa normalmente, a veces puede ser útil.