Respond to an unknown method call: Difference between revisions

Added FreeBASIC
(→‎{{header|Kotlin}}: Changed code so that the object itself now captures an attempt to call an unknown method.)
(Added FreeBASIC)
 
(33 intermediate revisions by 15 users not shown)
Line 15:
=={{header|AutoHotkey}}==
[http://ahkscript.org/boards/viewtopic.php?f=17&t=1363&start=140#p14454 Example by LinearSpoon]
<langsyntaxhighlight AutoHotkeylang="autohotkey">class example
{
foo()
Line 41:
ex := new example
ex.foo()
ex.bar(1,2)</langsyntaxhighlight>
 
=={{header|Brat}}==
<langsyntaxhighlight lang="brat">example = object.new
 
example.no_method = { meth_name, *args |
Line 50:
}
 
example.this_does_not_exist "at all" #Prints "this_does_not_exist was called with these arguments: [at all]"</langsyntaxhighlight>
 
=={{header|C sharp|C#}}==
{{works with|C sharp|4.0}}
 
<langsyntaxhighlight lang="csharp">using System;
using System.Dynamic;
 
Line 78:
ex.Bar();
}
}</langsyntaxhighlight>
 
=={{header|C++}}==
Line 86:
To avoid the pure virtual call, we can put some default function implementation into the abstract class which handles the situation (e.g. throws a custom exception or whatnot).
 
<langsyntaxhighlight lang="cpp">class animal {
public:
virtual void bark() // concrete virtual, not pure
Line 103:
e.bark(); // throws exception
}
</syntaxhighlight>
</lang>
 
=={{header|Caché ObjectScript}}==
Line 109:
Caché classes can include support for what is called dynamic dispatch. If dynamic dispatch is in use and a program references a property or method that is not part of the class definition, then a method (called a dispatch method) is called that attempts to resolve the undefined method or property. For example, dynamic dispatch can return a value for a property that is not defined or it can invoke a method for a method that is not implemented. The dispatch destination is dynamic in that it does not appear in the class descriptor and is not resolved until runtime.
 
<langsyntaxhighlight lang="cos">Class DynamicDispatch.Example Extends %RegisteredObject
{
 
Line 141:
}
 
}</langsyntaxhighlight>
{{out|Examples}}
<pre>
Line 155:
In Common Lisp, if a generic function is invoked on arguments for which there is no applicable specialized method, the method <code>no-applicable-method</code> is called with the generic function and the arguments.
 
<langsyntaxhighlight lang="lisp">(defgeneric do-something (thing)
(:documentation "Do something to thing."))
 
Line 162:
 
(defmethod do-something ((thing (eql 3)))
(format nil "Do something to ~w." thing))</langsyntaxhighlight>
 
Evaluating<langsyntaxhighlight lang="lisp">(list (do-something 3) (do-something 4))</langsyntaxhighlight> produces
 
<langsyntaxhighlight lang="lisp">("Do something to 3."
"No method for #<STANDARD-GENERIC-FUNCTION DO-SOMETHING 214FC042> on (4).")</langsyntaxhighlight>
 
=={{header|D}}==
Similar to the Python entry, but D performs this statically.
<langsyntaxhighlight lang="d">import std.stdio;
 
struct Catcher {
Line 195:
ca.grill();
ca.ding("dong", 11);
}</langsyntaxhighlight>
{{out}}
<pre>This is foo
Line 201:
Tried to handle unknown method 'grill'
Tried to handle unknown method 'ding', with arguments: dong 11 </pre>
 
=={{header|Déjà Vu}}==
The function <code>set-default</code> is useful here:
<langsyntaxhighlight lang="dejavu">}
labda:
print "One!"
Line 220 ⟶ 221:
obj!two
obj!three
</syntaxhighlight>
</lang>
{{out}}
<pre>One!
Line 232 ⟶ 233:
Practically, the object definition syntax provides a ''matcher'' clause to handle unrecognized messages. This example has the same behavior as the Python example.
 
<langsyntaxhighlight lang="e">def example {
to foo() { println("this is foo") }
to bar() { println("this is bar") }
Line 241 ⟶ 242:
}
}
}</langsyntaxhighlight>
=={{header|Elena}}==
Using generic handler (ELENA 3.2):
<lang elena>import extensions.
 
=={{header|Elena}}==
Using generic handler (ELENA 4.x):
<syntaxhighlight lang="elena">import extensions;
class Example
{
generic()
[{
// __received is an built-in variable containing the incoming message name
console printLine($subject," was invoked").
console.printLine(__received," was invoked")
]
}
generic : x
[generic(x)
{
console printLine($subject,"(",x,") was invoked").
console.printLine(__received,"(",x,") was invoked")
]
}
generic : x : y
[generic(x,y)
{
console printLine($subject,"(",x,",",y,") was invoked").
console.printLine(__received,"(",x,",",y,") was invoked")
]
}
}
 
public program()
program =
{
[
var o := Example new. Example();
o foo.foo();
o .bar(1).;
o .someMethod(1,2).
}</syntaxhighlight>
].</lang>
{{out}}
<pre>
Line 280 ⟶ 283:
 
=={{header|Fancy}}==
<langsyntaxhighlight lang="fancy">
class CatchThemAll {
def foo {
Line 301 ⟶ 304:
a we_can_do_it
a they_can_too: "eat" and: "walk"
</syntaxhighlight>
</lang>
 
=={{header|Fantom}}==
Line 307 ⟶ 310:
In Fantom, you can call methods statically or dynamically. Static calls to methods will be checked at compile time. Dynamic method calls (indicated by an <code>instance->method</code> syntax) are run through a "[http://fantom.org/doc/sys/Obj.html#trap trap]" method at run time. This method looks up the given method name, and throws an exception if the method/field is not known. This exception can be caught, and processed specially:
 
<langsyntaxhighlight lang="fantom">
class A
{
Line 340 ⟶ 343:
}
}
</syntaxhighlight>
</lang>
 
Output:
Line 355 ⟶ 358:
Needs the FMS-SI (single inheritance) library code located here:
http://soton.mpeforth.com/flag/fms/index.html
<langsyntaxhighlight lang="forth">include FMS-SI.f
include FMS-SILib.f
 
var x \ instantiate a class var object named x
x add: \ => "aborted: message not understood"
</syntaxhighlight>
</lang>
 
=={{header|FreeBASIC}}==
FreeBASIC does not support object-oriented programming, but we can handle the invocation of an undefined method on an object using a data structure such as a dictionary that maps method names to functions. If the method is not defined in the dictionary, you can provide a default response.
<syntaxhighlight lang="vbnet">Type Method
Func As Function() As String
End Type
 
Function DefaultMethod() As String
Return "no such method"
End Function
 
Type Objeto
Methods As Method Ptr
End Type
 
Sub Invoke(obj As Objeto, methodName As String)
If methodName = "exists" Then
Print obj.Methods->Func()
Else
Print DefaultMethod()
End If
End Sub
 
Function exists() As String
Return "exists"
End Function
 
Function CreateObject() As Objeto
Dim As Objeto obj
Dim As Method met
met.Func = @exists
obj.Methods = @met
Return obj
End Function
 
Dim As Objeto o = CreateObject()
Invoke(o, "exists")
Invoke(o, "non_existent_method")
 
Sleep</syntaxhighlight>
{{out}}
<pre>exists
no such method</pre>
 
=={{header|Go}}==
This uses reflection as in [[Send an unknown method call#Go]], but goes one more step to put the reflection code in a method. This allows an unknown method call to be handled by this method of the receiving object.
<langsyntaxhighlight lang="go">package main
 
import (
Line 392 ⟶ 438:
fmt.Println(e.CallMethod("Foo"))
fmt.Println(e.CallMethod("Bar"))
}</langsyntaxhighlight>
{{out}}
<pre>
Line 402 ⟶ 448:
=={{header|Groovy}}==
Groovy allows us to capture all unknown method calls using the methodMissing function
<langsyntaxhighlight lang="groovy">class MyObject {
def foo() {
println 'Invoked foo'
Line 409 ⟶ 455:
println "Invoked missing method $name$args"
}
}</langsyntaxhighlight>
 
Testing:
<langsyntaxhighlight lang="groovy">def o = new MyObject()
o.foo()
o.bar()
o.bar(1, 2, 'Test')</langsyntaxhighlight>
 
{{out}}
Line 433 ⟶ 479:
The example below is based upon the last case. The procedure 'DynMethod' would be used in place of normal method invocation. A special method 'UndefinedMethod' can be defined to handle unknown methods. The procedure 'DynMethod' requires knowledge of the internals of the code emitted to support objects.
 
<langsyntaxhighlight Uniconlang="unicon">procedure DynMethod(obj,meth,arglist[])
local m
 
Line 448 ⟶ 494:
return obj.UndefinedMethod!arglist # ... call it
else runerr(207,obj) # error invalid method (i.e. field)
end</langsyntaxhighlight>
 
<langsyntaxhighlight Uniconlang="unicon">procedure main()
x := foo()
y := foo2()
Line 480 ⟶ 526:
return
end
end</langsyntaxhighlight>
 
=={{header|Io}}==
{{trans|Python}}
 
<langsyntaxhighlight lang="io">Example := Object clone do(
foo := method(writeln("this is foo"))
bar := method(writeln("this is bar"))
Line 502 ⟶ 548:
example grill // prints "tried to handle unknown method grill"
example ding("dong") // prints "tried to handle unknown method ding"
// prints "it had arguments: list("dong")"</langsyntaxhighlight>
 
=={{header|J}}==
Line 509 ⟶ 555:
 
For example, we could define
<langsyntaxhighlight Jlang="j">example=:3 :0
doSomething_z_=: assert&0 bind 'doSomething was not implemented'
doSomething__y ''
Line 515 ⟶ 561:
 
doSomething_adhoc1_=: smoutput bind 'hello world'
dSomethingElse_adhoc2_=: smoutput bind 'hello world'</langsyntaxhighlight>
 
With those definitions in a fresh session (where <code>adhoc2</code> has not been given a definition for <code>doSomething</code>), we get the following behavior:
 
<langsyntaxhighlight Jlang="j"> example <'adhoc1'
hello world
example<'adhoc2'
|doSomething was not implemented: assert</langsyntaxhighlight>
 
(Note that need to have a cover verb (or adverb or conjunction) for the method call if you want to abstract it or dynamically intercept previously undefined methods.)
 
(Also, if we were using arbitrary method names, we would also want to introduce a check <code>_1=nc&lt;name</code> so that our default behavior does not override existing implementation.)
 
=={{header|JavaScript}}==
Line 531 ⟶ 579:
{{works with|Firefox}}
{{works with|IE}}
<langsyntaxhighlight lang="javascript">
obj = new Proxy({},
{ get : function(target, prop)
Line 546 ⟶ 594:
obj.l = function() {console.log(45);};
obj.l(); ///45
</syntaxhighlight>
</lang>
Where {} is the object to wrap in the proxy, but it could be a reference to another object, and the second argument to proxy´s constructor are the handlers that supersede the behavior of the target ({}), the 'get' function gets executed '''every time''' a property from target ({}) is needed, in this case, only if the property didn´t existed before, it returns the dynamically generated function.
 
Line 553 ⟶ 601:
 
Before Proxy interface, firefox (only) supported a suitable trap:<br>
<langsyntaxhighlight lang="javascript">var example = new Object;
example.foo = function () {
alert("this is foo");
Line 570 ⟶ 618:
example.grill(); // alerts "tried to handle unknown method grill"
example.ding("dong"); // alerts "tried to handle unknown method ding"
// alerts "it had arguments: dong</langsyntaxhighlight>
 
=={{header|Julia}}==
Julia will throw a MethodError exception if its multiple dispatch cannot find a proper function for a given set of arguments. This exception can be caught and resolved within a generically typed function that is not specific as to the object type of its arguments.
<langsyntaxhighlight lang="julia">
function add(a, b)
try
Line 588 ⟶ 636:
println(add(1//2, 1//2))
println(add("Hello ", "world"))
</syntaxhighlight>
</lang>
 
=={{header|Kotlin}}==
Kotlin JS does not currently target ECMAScript 2015 and so the Proxy object cannot be used for this task. The only way it can currently be accomplished is to use the Mozilla extension __noSuchMethod__ property which works with FireFoxFirefox 43 but is no longer supported by more up to date versions:
<langsyntaxhighlight lang="scala">// Kotlin JS version 1.2.0 (FireFoxFirefox 43)
 
class C {
Line 605 ⟶ 653:
val c: dynamic = C() // 'dynamic' turns off compile time checks
c.foo() // the compiler now allows this call even though foo() is undefined
}</langsyntaxhighlight>
 
{{out}}
Line 616 ⟶ 664:
 
If this is not included in the type, an error will result that may terminate processing unless otherwise handled.
<langsyntaxhighlight Lassolang="lasso">define exampletype => type {
public foo() => {
return 'this is foo\r'
Line 642 ⟶ 690:
 
#e->dothis('here',12,'there','nowhere')
// outputs 'tried to handle unknown method called "dothis" with args: "here,12,there,nowhere"'</langsyntaxhighlight>
 
=={{header|Logtalk}}==
Line 648 ⟶ 696:
There are two ways to handle unknown messages. From the sender side, we can catch the exception that is generated when an object doesn't understand a message:
 
<langsyntaxhighlight lang="logtalk">
:- object(foo).
 
Line 660 ⟶ 708:
 
:- end_object.
</syntaxhighlight>
</lang>
 
From the receiver side, an object can implement the built-in protocol "forwarding", defining the handler for messages that it doesn't understand (e.g. by forwarding or delegating it to another object):
 
<langsyntaxhighlight lang="logtalk">
:- object(foo,
implements(forwarding)).
Line 673 ⟶ 721:
 
:- end_object.
</syntaxhighlight>
</lang>
 
=={{header|Lua}}==
Line 679 ⟶ 727:
This is specifically the purpose of the __index metamethod:
 
<syntaxhighlight lang="lua">
<lang Lua>
local object={print=print}
setmetatable(object,{__index=function(t,k)return function() print("You called the method",k)end end})
object.print("Hi") -->Hi
object.hello() -->You called the method hello
</syntaxhighlight>
</lang>
 
=={{header|MathematicaM2000 Interpreter}}==
Normally we can't get an exception from object when we call an unknown method (module in M2000). The exception raised from the caller.
 
 
So here we have a custom invoke, three of them, one for modules, two for functions (for numeric and string values).
 
 
Each of them before actually invoke the method, check if the method exist, and if exist then make the call.
 
 
To check if a method exist we make a group (user object in M2000) with that method with an empty block for code, and we use Valid() to see if the left object has all the members of the right (where we have the one we want to check).
 
 
 
<syntaxhighlight lang="m2000 interpreter">
module checkit {
Class Alfa {
k=1000
module a (x, y) {
Print x, y
}
module NoParam {
Print "ok"
}
Function Sqr(x) {
=Sqrt(x)
}
Function NoParam {
=.k
}
Function Sqr$(x) {
=Str$(Sqrt(x),1033) ' using locale 1033, no leading space for positive
}
}
\\ modules, functions numeric and string, and variables can use same name
\\ here we have module invoke, function invoke, and function invoke$
Module invoke (&a, method$) {
param=(,)
Read ? param
Function Check(&a, method$) {
group b type "module "+method$+" {}"
=valid(@a as b)
}
if check(&a, method$) then {
for a {
\\ we call this.methodname
call "."+method$, !param
}
} else Flush : Error "unknown method "+method$ ' flush empty the stack
}
Function invoke (&a, method$) {
\\ functions have own stack of values
Function Check(&a, method$) {
group b type "Function "+filter$(method$, "()")+" {}"
=valid(@a as b)
}
if check(&a, method$) then {
for a {
=Function("."+method$, ![])
}
} else Error "unknown Function "+method$
}
\\ invoke string functions
Function invoke$ (&a, method$) {
\\ functions have own stack of values
Function Check(&a, method$) {
group b type "Function "+filter$(method$, "()")+" {}"
=valid(@a as b)
}
if check(&a, method$) then {
for a {
\\ [] is a function which return current stack as a stack object, and pass to current stack a new stack object.
=Function$("."+method$, ![])
}
} else Error "unknown Function "+method$
}
Module obj.alfa {
Flush 'empty stack
Print "this is a fake module, is not part of obj"
}
Function obj.alfa {
Print "this is a fake function, is not part of obj"
}
Obj=Alfa()
\\ normal invoke, interpreter not know that this is an object method
\\ this method has a weak reference to obj, so anytime we use This. or just dot, this weak reference make the real name to execute
Obj.a 10,20
\\ call the fake method (can't access object methods and properties), has empty weak reference to object
obj.alfa 10, 20
\\ check before call using custom invoke
\\ to check if a method (module) exist, we have to compare this object with other temporary object
\\ we make one with the method name and empty definition, and then check if obj has anything this temp object has
\\ arguments passed in a tuple (optional), so we didn't leave stack with unused items, if we have an unknown method.
invoke &obj, "a", (10, 20)
invoke &obj, "NoParam"
\\ now with an unknown method, using alfa
Try ok {
invoke &obj, "Alfa", (10, 20)
}
If Error Then Print Error$
\\ we can use invoke for functions
Print Invoke(&obj, "Sqr()", 4), Invoke(&obj, "NoParam()")
Print Invoke$(&obj, "Sqr$()",2)
\ without custom invoke
Print obj.Sqr(4), obj.Noparam(), obj.Sqr$(2)
\\ so now we try to call Alfa() and Alfa$() (unknown functions)
Try ok {
Print Invoke(&obj, "Alfa()")
}
If Error Then Print Error$
Try ok {
Print Invoke$(&obj, "Alfa$()")
}
If Error Then Print Error$
\\ so now lets copy obj to obj2
\\ fake method didn't passed to new object
obj2=obj
Try ok {
invoke &obj2, "alfa", (10, 20)
}
If Error Then Print Error$
p->obj2
\\ if p is a pointer to named group we can pass it as is
invoke &p, "a", (10, 20)
\\ normal called
p=>a 10,20
For p {
invoke &this, "a", (10, 20)
Try ok {
invoke &this, "alfa", (10, 20)
}
If Error Then Print Error$
}
p->(obj2) ' p point to a copy of obj2 (an unnamed group)
For p {
invoke &this, "a", (10, 20)
\\ normal called
p=>a 10, 20
Try ok {
invoke &this, "alfa", (10, 20)
}
If Error Then Print Error$
}
}
checkit
</syntaxhighlight>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
By default, when evaluating a symbol's <code>DownValues</code>, Mathematica picks the most specific.
<langsyntaxhighlight Mathematicalang="mathematica">obj[foo] = "This is foo.";
obj[bar] = "This is bar.";
obj[f_Symbol] := "What is " <> SymbolName[f] <> "?";
Print[obj@foo];
Print[obj@bar];
Print[obj@baz];</langsyntaxhighlight>
{{out}}
<pre>This is foo.
This is bar.
What is baz?</pre>
 
=={{header|Nim}}==
Nim statically checks that all methods exist, so this is generally not applicable.
However, it's possible to fake this behaviour using an experimental Nim feature
<syntaxhighlight lang="nim">{.experimental:"dotOperators".}
from strutils import join
 
type Foo = object
proc qux(f:Foo) = echo "called qux"
 
#for nicer output
func quoteStrings[T](x:T):string = (when T is string: "\"" & x & "\"" else: $x)
 
#dot operator catches all unmatched calls on Foo
template `.()`(f:Foo,field:untyped,args:varargs[string,quoteStrings]):untyped =
echo "tried to call method '" & astToStr(`field`) & (if `args`.len > 0: "' with args: " & args.join(", ") else: "'")
 
let f = Foo()
f.bar()
#f.bar #error: undeclared field
f.baz("hi",5)
f.qux()
f.qux("nope")</syntaxhighlight>
{{out}}
<pre>tried to call method 'bar'
tried to call method 'baz' with args: "hi", 5
called qux
tried to call method 'qux' with args: "nope"</pre>
 
=={{header|Object Pascal}}==
Works with FPC(tested with version 3.2.2).
{{incorrect|Object Pascal|Fails to meet at least two requirements. 1) Defining an abstract method constitutes predefining the method; bark is not an unknown method, but a known, unimplemented method. 2) The animal object isn't handling the situation; the caller gets an exception.}}
 
The example uses the late binding mechanism provided by custom variants. This will require some boilerplate code that needs to be placed in a separate unit:
An exception about calling a virtual method will be raised and interrupt the current code flow. But in that situation, the function is actually known. The concept of a function not being known at all does not exist in Object Pascal, due to static name lookup checking. That is to say, the call a.b() causes the compiler to verify that the symbol b exists in the namespace associated with expression a, and refers to a function.
<syntaxhighlight lang="pascal">
unit MyObjDef;
{$mode objfpc}{$h+}
interface
 
uses
To avoid the possibility of an abstract method call, one common solution is to leave an empty implementation for the virtual method instead of making it abstract. This is what an abstract method call looks like:
SysUtils, Variants;
 
function MyObjCreate: Variant;
<lang pascal>
type
Tanimal = class
public
procedure bark(); virtual; abstract;
end;
 
implementation
 
var
MyObjType: TInvokeableVariantType;
animal: Tanimal;
 
type
TMyObjType = class(TInvokeableVariantType)
procedure Clear(var V: TVarData); override;
procedure Copy(var aDst: TVarData; const aSrc: TVarData; const Indir: Boolean); override;
function GetProperty(var aDst: TVarData; const aData: TVarData; const aName: string): Boolean; override;
end;
 
function MyObjCreate: Variant;
begin
Result := Unassigned;
TVarData(Result).VType := MyObjType.VarType;
end;
 
procedure TMyObjType.Clear(var V: TVarData);
begin
V.VType := varEmpty;
end;
 
procedure TMyObjType.Copy(var aDst: TVarData; const aSrc: TVarData; const Indir: Boolean);
begin
VarClear(Variant(aDst));
aDst := aSrc;
end;
 
function TMyObjType.GetProperty(var aDst: TVarData; const aData: TVarData; const aName: string): Boolean;
begin
Result := True;
case LowerCase(aName) of
'bark': Variant(aDst) := 'WOF WOF!';
'moo': Variant(aDst) := 'Mooo!';
else
Variant(aDst) := Format('Sorry, what is "%s"?', [aName]);
end;
end;
 
initialization
MyObjType := TMyObjType.Create;
finalization
MyObjType.Free;
end.
</syntaxhighlight>
 
And main program:
animal := Tanimal.Create;
<syntaxhighlight lang="pascal">
animal.bark(); // abstract method call exception at runtime here
program Test;
animal.Free;
{$mode objfpc}{$h+}
uses
MyObjDef;
 
var
MyObj: Variant;
 
begin
MyObj := MyObjCreate;
WriteLn(MyObj.Bark);
WriteLn(MyObj.Moo);
WriteLn(MyObj.Meow);
end.
</syntaxhighlight>
</lang>
{{out}}
<pre>
WOF WOF!
Mooo!
Sorry, what is "Meow"?
</pre>
 
=={{header|Objective-C}}==
<code>-forwardInvocation:</code> is usually used to "forward" the message on to another object to handle.
 
<langsyntaxhighlight lang="objc">#include <Foundation/Foundation.h>
 
// The methods need to be declared somewhere
Line 791 ⟶ 1,082:
}
return 0;
}</langsyntaxhighlight>
 
 
=={{header|Oforth}}==
Line 800 ⟶ 1,090:
Method call is resolved at runtime : oforth looks at the top of the stack (that will become the method receiver) and searchs for a valid implementation of the method called (into receiver class or its parents). If no implementation is found for this method, doesNotUnderstand method is called instead.
 
<langsyntaxhighlight Oforthlang="oforth">1 first
[1:interpreter] ExRuntime : 1 does not understand method <#first></langsyntaxhighlight>
 
<langsyntaxhighlight Oforthlang="oforth">1 "first" asMethod perform
[1:interpreter] ExRuntime : 1 does not understand method <#first></langsyntaxhighlight>
 
Oforth has not concept such as "unknow method" : if a method exists, it can be called (even if the object on top of stack does not understand it). If not, no call is possible.
 
<langsyntaxhighlight Oforthlang="oforth">1 "unknow_method" asMethod perform
[1:interpreter] ExRuntime : null does not understand method <#perform></langsyntaxhighlight>
 
doesNotUnderstand can be redefined for a particular class :
 
<langsyntaxhighlight Oforthlang="oforth">Object Class new: MyClass
MyClass method: doesNotUnderstand(m)
"Well, sorry, I don't understand " print m println ;
 
MyClass new first
Well, sorry, I don't understand #first</langsyntaxhighlight>
 
=={{header|ooRexx}}==
To respond to unknown method calls, classes can implement an <code>unknown</code> method. This method is passed the name of the method and an array of the arguments that were used on the call.
<syntaxhighlight lang="oorexx">u = .unknown~new
<lang ooRexx>
u = .unknown~new
u~foo(1, 2, 3)
 
Line 829 ⟶ 1,118:
::method unknown
use arg name, args
say "Unknown method" name "invoked with arguments:" args~tostring('l', ', ')</syntaxhighlight>
</lang>
Output:
<pre>Unknown method FOO invoked with arguments: 1, 2, 3</pre>
<pre>
Unknown method FOO invoked with arguments: 1, 2, 3
</pre>
 
=={{header|Oz}}==
To respond to unknown method calls, classes can implement the <code>otherwise</code> method. As its sole argument, this method gets the received message, i.e. a record with the name of the unknown method as its label and the arguments as the record features.
<langsyntaxhighlight lang="oz">declare
class Example
meth init skip end
Line 860 ⟶ 1,146:
{Object bar}
{Object grill}
{Object ding(dong)}</langsyntaxhighlight>
 
Output:
Line 872 ⟶ 1,158:
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">package Example;
sub new {
bless {}
Line 901 ⟶ 1,187:
$example->grill; # prints "tried to handle unknown method Example::grill"
$example->ding("dong"); # prints "tried to handle unknown method Example::ding"
# and "it had arguments: dong"</langsyntaxhighlight>
=={{header|Perl 6}}==
 
=={{header|Phix}}==
<lang perl6>class Farragut {
Phix is not object orientated, but this sort of thing is very easy to emulate.
method FALLBACK ($name, *@rest) {
<!--<syntaxhighlight lang="phix">(phixonline)-->
say "{self.WHAT.perl}: $name.tc() the @rest[], full speed ahead!";
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
}
<span style="color: #008080;">enum</span> <span style="color: #000000;">METHODS</span>
}
 
<span style="color: #008080;">function</span> <span style="color: #000000;">invoke</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">o</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">name</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">args</span><span style="color: #0000FF;">={})</span>
class Sparrow is Farragut { }
<span style="color: #000080;font-style:italic;">--(this works on any class, for any function, with any number or type of parameters)</span>
 
<span style="color: #004080;">integer</span> <span style="color: #000000;">mdict</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">o</span><span style="color: #0000FF;">[</span><span style="color: #000000;">METHODS</span><span style="color: #0000FF;">]</span>
Farragut.damn: 'torpedoes';
<span style="color: #004080;">integer</span> <span style="color: #000000;">node</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getd_index</span><span style="color: #0000FF;">(</span><span style="color: #000000;">name</span><span style="color: #0000FF;">,</span><span style="color: #000000;">mdict</span><span style="color: #0000FF;">)</span>
Sparrow.hoist: <Jolly Roger mateys>;</lang>
<span style="color: #008080;">if</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">call_func</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">getd_by_index</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">,</span><span style="color: #000000;">mdict</span><span style="color: #0000FF;">),</span><span style="color: #000000;">args</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #008000;">"no such method"</span> <span style="color: #000080;font-style:italic;">-- or throw(), fatal(), etc</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #000080;font-style:italic;">--class X: Xmethods emulates a vtable</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">Xmethods</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new_dict</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">exists</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">return</span> <span style="color: #008000;">"exists"</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"exists"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">routine_id</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"exists"</span><span style="color: #0000FF;">),</span><span style="color: #000000;">Xmethods</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--class X: create new instances</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">newX</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">Xmethods</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">newX</span><span style="color: #0000FF;">()</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">invoke</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"exists"</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">invoke</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"non_existent_method"</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
<pre>Farragut: Damn the torpedoes, full speed ahead!
"exists"
Sparrow: Hoist the Jolly Roger mateys, full speed ahead!</pre>
"no such method"
 
</pre>
<tt>[http://design.perl6.org/S12.html#FALLBACK_methods FALLBACK]</tt> will be called for any method that is not defined. Since any class inherits from <tt>Any</tt>, there will be plenty of already defined methods. Those which are not defined can also be used as L-Values by the magic of <tt>[http://design.perl6.org/S12.html#Lvalue_methods is rw]</tt>.
 
<lang perl6>class L-Value {
our $.value = 10;
method FALLBACK($name, |c) is rw { $.value }
}
 
my $l = L-Value.new;
say $l.any-odd-name; # 10
$l.some-other-name = 42;
say $l.i-dont-know; # 42</lang>
 
=={{header|PHP}}==
<langsyntaxhighlight lang="php"><?php
class Example {
function foo() {
Line 953 ⟶ 1,253:
$example->ding("dong"); // prints "tried to handle unknown method ding"
// prints "it had arguments: dong
?></langsyntaxhighlight>
 
=={{header|PicoLisp}}==
The function '[http://software-lab.de/doc/refT.html#try try]' is used to send a message to an object for which it is not known whether it inherits a method for that message or not. As opposed to the syntacically equivalent '[http://software-lab.de/doc/refS.html#send send]' function, 'try' does not give an error, but returns NIL. We might redefine 'send' to get an effect analog to CLOS.
<langsyntaxhighlight PicoLisplang="picolisp">(redef send (Msg Obj . @)
(or
(pass try Msg Obj)
Line 968 ⟶ 1,268:
 
(dm do-something> ()
(pack "Do something to " This) )</langsyntaxhighlight>
Test:
<langsyntaxhighlight PicoLisplang="picolisp">: (object 'A '(+A))
-> A
: (object 'B '(+B))
-> B
: (list (send 'do-something> 'A) (send 'do-something> 'B))
-> ("Do something to A" "No method for do-something> on B")</langsyntaxhighlight>
 
=={{header|Pike}}==
{{incorrect|Pike|the <code>-></code> operator responds to all method calls, not just the unknown ones. the example needs to be amended to show how known methods are accessed }}
Pike allows to overload the <code>-></code> operator used to access object members:
<langsyntaxhighlight Pikelang="pike">class CatchAll
{
mixed `->(string name)
Line 990 ⟶ 1,291:
you are calling hello(5);
> CatchAll()->something(99);
you are calling something(99);</langsyntaxhighlight>
 
=={{header|Python}}==
Python objects can implement a <code>__getattr__()</code> method to handle accesses of unknown attributes (methods are just attributes that are callable; so this function handles both methods and non-method fields). Here we assume that if you access an unknown attribute, you want a method, so we return a function that can be called.
<langsyntaxhighlight lang="python">class Example(object):
def foo(self):
print("this is foo")
Line 1,012 ⟶ 1,313:
example.grill() # prints “tried to handle unknown method grill”
example.ding("dong") # prints “tried to handle unknown method ding”
# prints “it had arguments: ('dong',)”</langsyntaxhighlight>
 
=={{header|Racket}}==
Racket's usual object system can't deal with unknown methods, but we can capture the relevant exception and deal with it:
<langsyntaxhighlight lang="racket">
#lang racket
 
Line 1,042 ⟶ 1,343:
(send~ o foo 1) ; => foo: 1
(send~ o whatever 1) ; Unknown method whatever: (1)
</syntaxhighlight>
</lang>
 
Alternatively, we can use Swindle for a CLOS-like object system, and do something similar to the Common Lisp solution:
<langsyntaxhighlight lang="racket">
#lang swindle
 
Line 1,058 ⟶ 1,359:
(foo "one")
;; => No method in #<generic:foo> for "one"
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2020.08.1}}
<syntaxhighlight lang="raku" line>class Farragut {
method FALLBACK ($name, *@rest) {
say "{self.WHAT.raku}: $name.tc() the @rest[], full speed ahead!";
}
}
 
class Sparrow is Farragut { }
 
Farragut.damn: 'torpedoes';
Sparrow.hoist: <Jolly Roger mateys>;</syntaxhighlight>
{{out}}
<pre>Farragut: Damn the torpedoes, full speed ahead!
Sparrow: Hoist the Jolly Roger mateys, full speed ahead!</pre>
 
<tt>[https://docs.raku.org/language/typesystem#index-entry-FALLBACK_(method) FALLBACK]</tt> will be called for any method that is not defined. Since any class inherits from <tt>Any</tt>, there will be plenty of already defined methods. Those which are not defined can also be used as L-Values by the magic of <tt>[https://docs.raku.org/type/Attribute#index-entry-trait_is_rw_(Attribute)-trait_is_rw is rw]</tt>.
 
<syntaxhighlight lang="raku" line>class L-Value {
our $.value = 10;
method FALLBACK($name, |c) is rw { $.value }
}
 
my $l = L-Value.new;
say $l.any-odd-name; # 10
$l.some-other-name = 42;
say $l.i-dont-know; # 42</syntaxhighlight>
 
=={{header|Ring}}==
<syntaxhighlight lang="ring">
load "stdlibcore.ring"
 
new test {
anyMethodThatDoesNotExist() # Define and call the new method
anyMethodThatDoesNotExist() # Call the new method
}
class test
func braceerror
if substr(cCatchError,"Error (R3)")
? "You are calling a method that doesn't exist!"
aError = Split(cCatchError," ")
cMethodName = aError[len(aError)]
? "The Method Name: " + cMethodName
AddMethod(self,cMethodName,func {
? "Hello from the new method!"
})
? "We defined the new method!"
call cMethodName()
ok
</syntaxhighlight>
{{out}}
<pre>
You are calling a method that doesn't exist!
The Method Name: anymethodthatdoesnotexist
We defined the new method!
Hello from the new method!
Hello from the new method!
</pre>
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">class Example
def foo
puts "this is foo"
Line 1,082 ⟶ 1,444:
example.grill # prints “tried to handle unknown method grill”
example.ding("dong") # prints “tried to handle unknown method ding”
# prints “it had arguments: ["dong"]”</langsyntaxhighlight>
 
=={{header|Scala}}==
{{works with|Scala|2.9}}
As of scala 2.9, scalac must receive the -Xexperimental optional for Dynamic to receive this treatment.
<langsyntaxhighlight lang="scala">class DynamicTest extends Dynamic
{
def foo()=println("this is foo")
Line 1,107 ⟶ 1,469:
}
}
</syntaxhighlight>
</lang>
Output:
<pre>this is foo
Line 1,117 ⟶ 1,479:
=={{header|Sidef}}==
The special '''AUTOLOAD''' method gets called when a method isn't defined in the current class:
<langsyntaxhighlight lang="ruby">class Example {
method foo {
say "this is foo"
Line 1,138 ⟶ 1,500:
example.grill; # prints “tried to handle unknown method grill”
example.ding("dong"); # prints “tried to handle unknown method ding”
# prints “it had arguments: dong”</langsyntaxhighlight>
 
=={{header|Slate}}==
Line 1,144 ⟶ 1,506:
Here is an example of unknown methods being used to call shell commands (this is already defined in the base image):
 
<langsyntaxhighlight lang="slate">define: #shell &builder: [lobby newSubSpace].
 
_@shell didNotUnderstand: message at: position
Line 1,167 ⟶ 1,529:
ifFalse: [args do: [| :arg | command ; ' ' ; arg]]]]] writingAs: String)
ifNil: [resend] ifNotNilDo: [| :cmd | [Platform run: cmd]]]
].</langsyntaxhighlight>
 
Here is an example of it being used:
 
<langsyntaxhighlight lang="slate">slate[1]> shell ls: '*.image'.
kernel.new.little.64.1244260494374694.image slate2.image
net.image slate.image
True
slate[2]></langsyntaxhighlight>
 
 
=={{header|Smalltalk}}==
{{works with|GNU Smalltalk}}
 
<langsyntaxhighlight lang="smalltalk">Object subclass: CatchThemAll [
foo [ 'foo received' displayNl ]
 
Line 1,198 ⟶ 1,559:
a bar.
a weCanDoIt.
a theyCanToo: 'eat' and: 'walk'.</langsyntaxhighlight>
 
There are two ways to catch unimplemented messages:
* on the receiver side, by redefining the "doesNotUnderstand:" method in the receiver class hierarchy, as shown above.
* on the sender side, by catching the MessageNotUnderstood exception, as follows:
<langsyntaxhighlight lang="smalltalk">[
bla := someObject fooBar.
foo := bla.
] on: MessageNotUnderstood do:[:ex |
ex return: 'fortyTwo'
]</langsyntaxhighlight>
this will leave 'fortyTwo' on bla AND foo (because the handler proceeds).
This sender-side handling is useful if you don't want to or if you are not allowed to change the receiver's class hierarchy (which is not a technical, but solely a political/conventional limitation, because in Smalltalk no class is closed, and extensions can be added to any class simply by loading or dynamically adding methods - even to the base system or third party packages).
Line 1,214 ⟶ 1,575:
Of course, this handler now catches any other unimplemented messages as well, thus if foobar was implemented, but itself sends another bad message, we'd catch that as well.
We can check for this in the handler, by checking for which message got us there:
<langsyntaxhighlight lang="smalltalk">[
bla := someObject fooBar.
foo := bla.
Line 1,224 ⟶ 1,585:
ex reject
]
]</langsyntaxhighlight>
the reject will re-reaise the exception, and lead us to an outer handler, or the debugger, if there is none.
{{works with|Smalltalk/X}}
There is a utility method for exactly the above (it catches only #fooBar to the original receiver):
<langsyntaxhighlight lang="smalltalk">anObject perform:#fooBar ifNotUnderstood:[ ...some alternative code and return value... ].</langsyntaxhighlight>
 
 
=={{header|SuperCollider}}==
<langsyntaxhighlight SuperColliderlang="supercollider">Ingorabilis {
 
tell {
Line 1,251 ⟶ 1,611:
 
}
</syntaxhighlight>
</lang>
Usage:
 
<syntaxhighlight lang="supercollider">
<lang SuperCollider>
i = Ingorabilis.new;
i.tell; // prints "I told you so"
i.find; // prints ""I found nothing"
i.think(1, 3, 4, 7);
</syntaxhighlight>
</lang>
 
The latter answers:
<langsyntaxhighlight SuperColliderlang="supercollider">Method selector 'think' not understood by Ingorabilis
Giving you some good arguments in the following
1
Line 1,274 ⟶ 1,634:
instance variables [0]
}
<...></langsyntaxhighlight>
Catch the method call:
<syntaxhighlight lang="supercollider">
<lang SuperCollider>
i = Ingorabilis.new
try { i.think } { "We are not delegating to super, because I don't want it".postln };
</syntaxhighlight>
</lang>
 
=={{header|Tcl}}==
{{works with|Tcl|8.6}} or {{libheader|TclOO}}
<langsyntaxhighlight lang="tcl">package require TclOO
# First create a simple, conventional class and object
oo::class create Example {
Line 1,310 ⟶ 1,670:
example grill; # prints “tried to handle unknown method "grill"”
example ding dong; # prints “tried to handle unknown method "ding"”
# prints “it had arguments: dong”</langsyntaxhighlight>
 
=={{header|UNIX Shell}}==
{{works with|Bash}}
bash doesn't have objects with methods, but it can handle unknown commands:
<langsyntaxhighlight Bashlang="bash">function handle_error {
status=$?
 
Line 1,331 ⟶ 1,691:
 
# Trap errors.
trap 'handle_error' ERR</langsyntaxhighlight>
Sample usage:
$ foo
bash: foo: command not found
you tried to call foo
 
=={{header|Wren}}==
Unlike some other dynamically typed languages, it is not possible to create new methods at runtime in Wren. Attempting to call an unknown method would therefore normally result in a fatal error. However, we can catch such an error and redirect it for user interaction as shown below.
<syntaxhighlight lang="wren">import "io" for Stdin, Stdout
 
class Test {
construct new() {}
 
foo() { System.print("Foo called.") }
 
bar() { System.print("Bar called.") }
 
missingMethod(m) {
System.print(m)
System.write("Try and continue anyway y/n ? ")
Stdout.flush()
var reply = Stdin.readLine()
if (reply != "y" && reply != "Y") {
Fiber.abort("Decided to abort due to missing method.")
}
}
}
 
var test = Test.new()
var f = Fiber.new {
test.foo()
test.bar()
test.baz()
}
f.try()
var err = f.error
if (err) {
if (err.startsWith("Test does not implement")) {
test.missingMethod(err)
} else {
Fiber.abort(err) // rethrow other errors
}
}
System.print("OK, continuing.")</syntaxhighlight>
 
{{out}}
<pre>
Foo called.
Bar called.
Test does not implement 'baz()'.
Try and continue anyway y/n ? y
OK, continuing.
</pre>
 
Or alternatively:
<pre>
Foo called.
Bar called.
Test does not implement 'baz()'.
Try and continue anyway y/n ? n
Decided to abort due to missing method.
[./respond_to_unknown line 16] in missingMethod(_)
[./respond_to_unknown line 31] in (script)
</pre>
 
=={{header|zkl}}==
If something can not be resolved (in a class) the function __notFound is called. It can redirect to another object.
<langsyntaxhighlight lang="zkl">class C{ fcn __notFound(name){println(name," not in ",self); bar}
fcn bar{vm.arglist.println("***")}
}</langsyntaxhighlight>
<pre>
C.foo //-->"foo not in Class(C)", returns Fcn(bar)
Line 1,365 ⟶ 1,784:
{{omit from|OCaml}}
{{omit from|PARI/GP}}
{{omit from|Phix}}
{{omit from|PowerShell}}
{{omit from|Processing}}
{{omit from|PureBasic}}
{{omit from|Retro}}
{{omit from|Rust}}
{{omit from|Swift}}
{{omit from|TI-89 BASIC}} <!-- No objects -->
2,122

edits