Respond to an unknown method call: Difference between revisions

Content added Content deleted
m (syntax highlighting fixup automation)
Line 15: Line 15:
=={{header|AutoHotkey}}==
=={{header|AutoHotkey}}==
[http://ahkscript.org/boards/viewtopic.php?f=17&t=1363&start=140#p14454 Example by LinearSpoon]
[http://ahkscript.org/boards/viewtopic.php?f=17&t=1363&start=140#p14454 Example by LinearSpoon]
<lang AutoHotkey>class example
<syntaxhighlight lang="autohotkey">class example
{
{
foo()
foo()
Line 41: Line 41:
ex := new example
ex := new example
ex.foo()
ex.foo()
ex.bar(1,2)</lang>
ex.bar(1,2)</syntaxhighlight>


=={{header|Brat}}==
=={{header|Brat}}==
<lang brat>example = object.new
<syntaxhighlight lang="brat">example = object.new


example.no_method = { meth_name, *args |
example.no_method = { meth_name, *args |
Line 50: Line 50:
}
}


example.this_does_not_exist "at all" #Prints "this_does_not_exist was called with these arguments: [at all]"</lang>
example.this_does_not_exist "at all" #Prints "this_does_not_exist was called with these arguments: [at all]"</syntaxhighlight>


=={{header|C sharp|C#}}==
=={{header|C sharp|C#}}==
{{works with|C sharp|4.0}}
{{works with|C sharp|4.0}}


<lang csharp>using System;
<syntaxhighlight lang="csharp">using System;
using System.Dynamic;
using System.Dynamic;


Line 78: Line 78:
ex.Bar();
ex.Bar();
}
}
}</lang>
}</syntaxhighlight>


=={{header|C++}}==
=={{header|C++}}==
Line 86: 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).
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).


<lang cpp>class animal {
<syntaxhighlight lang="cpp">class animal {
public:
public:
virtual void bark() // concrete virtual, not pure
virtual void bark() // concrete virtual, not pure
Line 103: Line 103:
e.bark(); // throws exception
e.bark(); // throws exception
}
}
</syntaxhighlight>
</lang>


=={{header|Caché ObjectScript}}==
=={{header|Caché ObjectScript}}==
Line 109: 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.
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.


<lang cos>Class DynamicDispatch.Example Extends %RegisteredObject
<syntaxhighlight lang="cos">Class DynamicDispatch.Example Extends %RegisteredObject
{
{


Line 141: Line 141:
}
}


}</lang>
}</syntaxhighlight>
{{out|Examples}}
{{out|Examples}}
<pre>
<pre>
Line 155: 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.
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.


<lang lisp>(defgeneric do-something (thing)
<syntaxhighlight lang="lisp">(defgeneric do-something (thing)
(:documentation "Do something to thing."))
(:documentation "Do something to thing."))


Line 162: Line 162:


(defmethod do-something ((thing (eql 3)))
(defmethod do-something ((thing (eql 3)))
(format nil "Do something to ~w." thing))</lang>
(format nil "Do something to ~w." thing))</syntaxhighlight>


Evaluating<lang lisp>(list (do-something 3) (do-something 4))</lang> produces
Evaluating<syntaxhighlight lang="lisp">(list (do-something 3) (do-something 4))</syntaxhighlight> produces


<lang lisp>("Do something to 3."
<syntaxhighlight lang="lisp">("Do something to 3."
"No method for #<STANDARD-GENERIC-FUNCTION DO-SOMETHING 214FC042> on (4).")</lang>
"No method for #<STANDARD-GENERIC-FUNCTION DO-SOMETHING 214FC042> on (4).")</syntaxhighlight>


=={{header|D}}==
=={{header|D}}==
Similar to the Python entry, but D performs this statically.
Similar to the Python entry, but D performs this statically.
<lang d>import std.stdio;
<syntaxhighlight lang="d">import std.stdio;


struct Catcher {
struct Catcher {
Line 195: Line 195:
ca.grill();
ca.grill();
ca.ding("dong", 11);
ca.ding("dong", 11);
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>This is foo
<pre>This is foo
Line 204: Line 204:
=={{header|Déjà Vu}}==
=={{header|Déjà Vu}}==
The function <code>set-default</code> is useful here:
The function <code>set-default</code> is useful here:
<lang dejavu>}
<syntaxhighlight lang="dejavu">}
labda:
labda:
print "One!"
print "One!"
Line 221: Line 221:
obj!two
obj!two
obj!three
obj!three
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>One!
<pre>One!
Line 233: Line 233:
Practically, the object definition syntax provides a ''matcher'' clause to handle unrecognized messages. This example has the same behavior as the Python example.
Practically, the object definition syntax provides a ''matcher'' clause to handle unrecognized messages. This example has the same behavior as the Python example.


<lang e>def example {
<syntaxhighlight lang="e">def example {
to foo() { println("this is foo") }
to foo() { println("this is foo") }
to bar() { println("this is bar") }
to bar() { println("this is bar") }
Line 242: Line 242:
}
}
}
}
}</lang>
}</syntaxhighlight>


=={{header|Elena}}==
=={{header|Elena}}==
Using generic handler (ELENA 4.x):
Using generic handler (ELENA 4.x):
<lang elena>import extensions;
<syntaxhighlight lang="elena">import extensions;
class Example
class Example
Line 274: Line 274:
o.bar(1);
o.bar(1);
o.someMethod(1,2)
o.someMethod(1,2)
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 283: Line 283:


=={{header|Fancy}}==
=={{header|Fancy}}==
<lang fancy>
<syntaxhighlight lang="fancy">
class CatchThemAll {
class CatchThemAll {
def foo {
def foo {
Line 304: Line 304:
a we_can_do_it
a we_can_do_it
a they_can_too: "eat" and: "walk"
a they_can_too: "eat" and: "walk"
</syntaxhighlight>
</lang>


=={{header|Fantom}}==
=={{header|Fantom}}==
Line 310: Line 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:
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:


<lang fantom>
<syntaxhighlight lang="fantom">
class A
class A
{
{
Line 343: Line 343:
}
}
}
}
</syntaxhighlight>
</lang>


Output:
Output:
Line 358: Line 358:
Needs the FMS-SI (single inheritance) library code located here:
Needs the FMS-SI (single inheritance) library code located here:
http://soton.mpeforth.com/flag/fms/index.html
http://soton.mpeforth.com/flag/fms/index.html
<lang forth>include FMS-SI.f
<syntaxhighlight lang="forth">include FMS-SI.f
include FMS-SILib.f
include FMS-SILib.f


var x \ instantiate a class var object named x
var x \ instantiate a class var object named x
x add: \ => "aborted: message not understood"
x add: \ => "aborted: message not understood"
</syntaxhighlight>
</lang>


=={{header|Go}}==
=={{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.
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.
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 395: Line 395:
fmt.Println(e.CallMethod("Foo"))
fmt.Println(e.CallMethod("Foo"))
fmt.Println(e.CallMethod("Bar"))
fmt.Println(e.CallMethod("Bar"))
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 405: Line 405:
=={{header|Groovy}}==
=={{header|Groovy}}==
Groovy allows us to capture all unknown method calls using the methodMissing function
Groovy allows us to capture all unknown method calls using the methodMissing function
<lang groovy>class MyObject {
<syntaxhighlight lang="groovy">class MyObject {
def foo() {
def foo() {
println 'Invoked foo'
println 'Invoked foo'
Line 412: Line 412:
println "Invoked missing method $name$args"
println "Invoked missing method $name$args"
}
}
}</lang>
}</syntaxhighlight>


Testing:
Testing:
<lang groovy>def o = new MyObject()
<syntaxhighlight lang="groovy">def o = new MyObject()
o.foo()
o.foo()
o.bar()
o.bar()
o.bar(1, 2, 'Test')</lang>
o.bar(1, 2, 'Test')</syntaxhighlight>


{{out}}
{{out}}
Line 436: Line 436:
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.
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.


<lang Unicon>procedure DynMethod(obj,meth,arglist[])
<syntaxhighlight lang="unicon">procedure DynMethod(obj,meth,arglist[])
local m
local m


Line 451: Line 451:
return obj.UndefinedMethod!arglist # ... call it
return obj.UndefinedMethod!arglist # ... call it
else runerr(207,obj) # error invalid method (i.e. field)
else runerr(207,obj) # error invalid method (i.e. field)
end</lang>
end</syntaxhighlight>


<lang Unicon>procedure main()
<syntaxhighlight lang="unicon">procedure main()
x := foo()
x := foo()
y := foo2()
y := foo2()
Line 483: Line 483:
return
return
end
end
end</lang>
end</syntaxhighlight>


=={{header|Io}}==
=={{header|Io}}==
{{trans|Python}}
{{trans|Python}}


<lang io>Example := Object clone do(
<syntaxhighlight lang="io">Example := Object clone do(
foo := method(writeln("this is foo"))
foo := method(writeln("this is foo"))
bar := method(writeln("this is bar"))
bar := method(writeln("this is bar"))
Line 505: Line 505:
example grill // prints "tried to handle unknown method grill"
example grill // prints "tried to handle unknown method grill"
example ding("dong") // prints "tried to handle unknown method ding"
example ding("dong") // prints "tried to handle unknown method ding"
// prints "it had arguments: list("dong")"</lang>
// prints "it had arguments: list("dong")"</syntaxhighlight>


=={{header|J}}==
=={{header|J}}==
Line 512: Line 512:


For example, we could define
For example, we could define
<lang J>example=:3 :0
<syntaxhighlight lang="j">example=:3 :0
doSomething_z_=: assert&0 bind 'doSomething was not implemented'
doSomething_z_=: assert&0 bind 'doSomething was not implemented'
doSomething__y ''
doSomething__y ''
Line 518: Line 518:


doSomething_adhoc1_=: smoutput bind 'hello world'
doSomething_adhoc1_=: smoutput bind 'hello world'
dSomethingElse_adhoc2_=: smoutput bind 'hello world'</lang>
dSomethingElse_adhoc2_=: smoutput bind 'hello world'</syntaxhighlight>


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:
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:


<lang J> example <'adhoc1'
<syntaxhighlight lang="j"> example <'adhoc1'
hello world
hello world
example<'adhoc2'
example<'adhoc2'
|doSomething was not implemented: assert</lang>
|doSomething was not implemented: assert</syntaxhighlight>


(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.)
(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.)
Line 536: Line 536:
{{works with|Firefox}}
{{works with|Firefox}}
{{works with|IE}}
{{works with|IE}}
<lang javascript>
<syntaxhighlight lang="javascript">
obj = new Proxy({},
obj = new Proxy({},
{ get : function(target, prop)
{ get : function(target, prop)
Line 551: Line 551:
obj.l = function() {console.log(45);};
obj.l = function() {console.log(45);};
obj.l(); ///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.
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 558: Line 558:


Before Proxy interface, firefox (only) supported a suitable trap:<br>
Before Proxy interface, firefox (only) supported a suitable trap:<br>
<lang javascript>var example = new Object;
<syntaxhighlight lang="javascript">var example = new Object;
example.foo = function () {
example.foo = function () {
alert("this is foo");
alert("this is foo");
Line 575: Line 575:
example.grill(); // alerts "tried to handle unknown method grill"
example.grill(); // alerts "tried to handle unknown method grill"
example.ding("dong"); // alerts "tried to handle unknown method ding"
example.ding("dong"); // alerts "tried to handle unknown method ding"
// alerts "it had arguments: dong</lang>
// alerts "it had arguments: dong</syntaxhighlight>


=={{header|Julia}}==
=={{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.
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.
<lang julia>
<syntaxhighlight lang="julia">
function add(a, b)
function add(a, b)
try
try
Line 593: Line 593:
println(add(1//2, 1//2))
println(add(1//2, 1//2))
println(add("Hello ", "world"))
println(add("Hello ", "world"))
</syntaxhighlight>
</lang>


=={{header|Kotlin}}==
=={{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 Firefox 43 but is no longer supported by more up to date versions:
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 Firefox 43 but is no longer supported by more up to date versions:
<lang scala>// Kotlin JS version 1.2.0 (Firefox 43)
<syntaxhighlight lang="scala">// Kotlin JS version 1.2.0 (Firefox 43)


class C {
class C {
Line 610: Line 610:
val c: dynamic = C() // 'dynamic' turns off compile time checks
val c: dynamic = C() // 'dynamic' turns off compile time checks
c.foo() // the compiler now allows this call even though foo() is undefined
c.foo() // the compiler now allows this call even though foo() is undefined
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 621: Line 621:


If this is not included in the type, an error will result that may terminate processing unless otherwise handled.
If this is not included in the type, an error will result that may terminate processing unless otherwise handled.
<lang Lasso>define exampletype => type {
<syntaxhighlight lang="lasso">define exampletype => type {
public foo() => {
public foo() => {
return 'this is foo\r'
return 'this is foo\r'
Line 647: Line 647:


#e->dothis('here',12,'there','nowhere')
#e->dothis('here',12,'there','nowhere')
// outputs 'tried to handle unknown method called "dothis" with args: "here,12,there,nowhere"'</lang>
// outputs 'tried to handle unknown method called "dothis" with args: "here,12,there,nowhere"'</syntaxhighlight>


=={{header|Logtalk}}==
=={{header|Logtalk}}==
Line 653: Line 653:
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:
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:


<lang logtalk>
<syntaxhighlight lang="logtalk">
:- object(foo).
:- object(foo).


Line 665: Line 665:


:- end_object.
:- 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):
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):


<lang logtalk>
<syntaxhighlight lang="logtalk">
:- object(foo,
:- object(foo,
implements(forwarding)).
implements(forwarding)).
Line 678: Line 678:


:- end_object.
:- end_object.
</syntaxhighlight>
</lang>


=={{header|Lua}}==
=={{header|Lua}}==
Line 684: Line 684:
This is specifically the purpose of the __index metamethod:
This is specifically the purpose of the __index metamethod:


<syntaxhighlight lang="lua">
<lang Lua>
local object={print=print}
local object={print=print}
setmetatable(object,{__index=function(t,k)return function() print("You called the method",k)end end})
setmetatable(object,{__index=function(t,k)return function() print("You called the method",k)end end})
object.print("Hi") -->Hi
object.print("Hi") -->Hi
object.hello() -->You called the method hello
object.hello() -->You called the method hello
</syntaxhighlight>
</lang>


=={{header|M2000 Interpreter}}==
=={{header|M2000 Interpreter}}==
Line 705: Line 705:




<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
module checkit {
module checkit {
Line 846: Line 846:
}
}
checkit
checkit
</syntaxhighlight>
</lang>


=={{header|Mathematica}}/{{header|Wolfram Language}}==
=={{header|Mathematica}}/{{header|Wolfram Language}}==
By default, when evaluating a symbol's <code>DownValues</code>, Mathematica picks the most specific.
By default, when evaluating a symbol's <code>DownValues</code>, Mathematica picks the most specific.
<lang Mathematica>obj[foo] = "This is foo.";
<syntaxhighlight lang="mathematica">obj[foo] = "This is foo.";
obj[bar] = "This is bar.";
obj[bar] = "This is bar.";
obj[f_Symbol] := "What is " <> SymbolName[f] <> "?";
obj[f_Symbol] := "What is " <> SymbolName[f] <> "?";
Print[obj@foo];
Print[obj@foo];
Print[obj@bar];
Print[obj@bar];
Print[obj@baz];</lang>
Print[obj@baz];</syntaxhighlight>
{{out}}
{{out}}
<pre>This is foo.
<pre>This is foo.
Line 864: Line 864:
Nim statically checks that all methods exist, so this is generally not applicable.
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
However, it's possible to fake this behaviour using an experimental Nim feature
<lang nim>{.experimental:"dotOperators".}
<syntaxhighlight lang="nim">{.experimental:"dotOperators".}
from strutils import join
from strutils import join


Line 883: Line 883:
f.baz("hi",5)
f.baz("hi",5)
f.qux()
f.qux()
f.qux("nope")</lang>
f.qux("nope")</syntaxhighlight>
{{out}}
{{out}}
<pre>tried to call method 'bar'
<pre>tried to call method 'bar'
Line 897: Line 897:
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:
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:


<lang pascal>
<syntaxhighlight lang="pascal">
type
type
Tanimal = class
Tanimal = class
Line 916: Line 916:


end.
end.
</syntaxhighlight>
</lang>


=={{header|Objective-C}}==
=={{header|Objective-C}}==
<code>-forwardInvocation:</code> is usually used to "forward" the message on to another object to handle.
<code>-forwardInvocation:</code> is usually used to "forward" the message on to another object to handle.


<lang objc>#include <Foundation/Foundation.h>
<syntaxhighlight lang="objc">#include <Foundation/Foundation.h>


// The methods need to be declared somewhere
// The methods need to be declared somewhere
Line 982: Line 982:
}
}
return 0;
return 0;
}</lang>
}</syntaxhighlight>


=={{header|Oforth}}==
=={{header|Oforth}}==
Line 990: Line 990:
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.
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.


<lang Oforth>1 first
<syntaxhighlight lang="oforth">1 first
[1:interpreter] ExRuntime : 1 does not understand method <#first></lang>
[1:interpreter] ExRuntime : 1 does not understand method <#first></syntaxhighlight>


<lang Oforth>1 "first" asMethod perform
<syntaxhighlight lang="oforth">1 "first" asMethod perform
[1:interpreter] ExRuntime : 1 does not understand method <#first></lang>
[1:interpreter] ExRuntime : 1 does not understand method <#first></syntaxhighlight>


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.
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.


<lang Oforth>1 "unknow_method" asMethod perform
<syntaxhighlight lang="oforth">1 "unknow_method" asMethod perform
[1:interpreter] ExRuntime : null does not understand method <#perform></lang>
[1:interpreter] ExRuntime : null does not understand method <#perform></syntaxhighlight>


doesNotUnderstand can be redefined for a particular class :
doesNotUnderstand can be redefined for a particular class :


<lang Oforth>Object Class new: MyClass
<syntaxhighlight lang="oforth">Object Class new: MyClass
MyClass method: doesNotUnderstand(m)
MyClass method: doesNotUnderstand(m)
"Well, sorry, I don't understand " print m println ;
"Well, sorry, I don't understand " print m println ;


MyClass new first
MyClass new first
Well, sorry, I don't understand #first</lang>
Well, sorry, I don't understand #first</syntaxhighlight>


=={{header|ooRexx}}==
=={{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.
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.
<lang ooRexx>u = .unknown~new
<syntaxhighlight lang="oorexx">u = .unknown~new
u~foo(1, 2, 3)
u~foo(1, 2, 3)


Line 1,018: Line 1,018:
::method unknown
::method unknown
use arg name, args
use arg name, args
say "Unknown method" name "invoked with arguments:" args~tostring('l',', ')</lang>
say "Unknown method" name "invoked with arguments:" args~tostring('l',', ')</syntaxhighlight>
Output:
Output:
<pre>Unknown method FOO invoked with arguments: 1, 2, 3</pre>
<pre>Unknown method FOO invoked with arguments: 1, 2, 3</pre>
Line 1,024: Line 1,024:
=={{header|Oz}}==
=={{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.
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.
<lang oz>declare
<syntaxhighlight lang="oz">declare
class Example
class Example
meth init skip end
meth init skip end
Line 1,046: Line 1,046:
{Object bar}
{Object bar}
{Object grill}
{Object grill}
{Object ding(dong)}</lang>
{Object ding(dong)}</syntaxhighlight>


Output:
Output:
Line 1,058: Line 1,058:


=={{header|Perl}}==
=={{header|Perl}}==
<lang perl>package Example;
<syntaxhighlight lang="perl">package Example;
sub new {
sub new {
bless {}
bless {}
Line 1,087: Line 1,087:
$example->grill; # prints "tried to handle unknown method Example::grill"
$example->grill; # prints "tried to handle unknown method Example::grill"
$example->ding("dong"); # prints "tried to handle unknown method Example::ding"
$example->ding("dong"); # prints "tried to handle unknown method Example::ding"
# and "it had arguments: dong"</lang>
# and "it had arguments: dong"</syntaxhighlight>


=={{header|Phix}}==
=={{header|Phix}}==
Phix is not object orientated, but this sort of thing is very easy to emulate.
Phix is not object orientated, but this sort of thing is very easy to emulate.
<!--<lang Phix>(phixonline)-->
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<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;">enum</span> <span style="color: #000000;">METHODS</span>
Line 1,123: Line 1,123:
<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;">"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>
<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>
<!--</lang>-->
<!--</syntaxhighlight>-->
{{out}}
{{out}}
<pre>
<pre>
Line 1,131: Line 1,131:


=={{header|PHP}}==
=={{header|PHP}}==
<lang php><?php
<syntaxhighlight lang="php"><?php
class Example {
class Example {
function foo() {
function foo() {
Line 1,153: Line 1,153:
$example->ding("dong"); // prints "tried to handle unknown method ding"
$example->ding("dong"); // prints "tried to handle unknown method ding"
// prints "it had arguments: dong
// prints "it had arguments: dong
?></lang>
?></syntaxhighlight>


=={{header|PicoLisp}}==
=={{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.
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.
<lang PicoLisp>(redef send (Msg Obj . @)
<syntaxhighlight lang="picolisp">(redef send (Msg Obj . @)
(or
(or
(pass try Msg Obj)
(pass try Msg Obj)
Line 1,168: Line 1,168:


(dm do-something> ()
(dm do-something> ()
(pack "Do something to " This) )</lang>
(pack "Do something to " This) )</syntaxhighlight>
Test:
Test:
<lang PicoLisp>: (object 'A '(+A))
<syntaxhighlight lang="picolisp">: (object 'A '(+A))
-> A
-> A
: (object 'B '(+B))
: (object 'B '(+B))
-> B
-> B
: (list (send 'do-something> 'A) (send 'do-something> 'B))
: (list (send 'do-something> 'A) (send 'do-something> 'B))
-> ("Do something to A" "No method for do-something> on B")</lang>
-> ("Do something to A" "No method for do-something> on B")</syntaxhighlight>


=={{header|Pike}}==
=={{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 }}
{{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:
Pike allows to overload the <code>-></code> operator used to access object members:
<lang Pike>class CatchAll
<syntaxhighlight lang="pike">class CatchAll
{
{
mixed `->(string name)
mixed `->(string name)
Line 1,191: Line 1,191:
you are calling hello(5);
you are calling hello(5);
> CatchAll()->something(99);
> CatchAll()->something(99);
you are calling something(99);</lang>
you are calling something(99);</syntaxhighlight>


=={{header|Python}}==
=={{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.
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.
<lang python>class Example(object):
<syntaxhighlight lang="python">class Example(object):
def foo(self):
def foo(self):
print("this is foo")
print("this is foo")
Line 1,213: Line 1,213:
example.grill() # prints “tried to handle unknown method grill”
example.grill() # prints “tried to handle unknown method grill”
example.ding("dong") # prints “tried to handle unknown method ding”
example.ding("dong") # prints “tried to handle unknown method ding”
# prints “it had arguments: ('dong',)”</lang>
# prints “it had arguments: ('dong',)”</syntaxhighlight>


=={{header|Racket}}==
=={{header|Racket}}==
Racket's usual object system can't deal with unknown methods, but we can capture the relevant exception and deal with it:
Racket's usual object system can't deal with unknown methods, but we can capture the relevant exception and deal with it:
<lang racket>
<syntaxhighlight lang="racket">
#lang racket
#lang racket


Line 1,243: Line 1,243:
(send~ o foo 1) ; => foo: 1
(send~ o foo 1) ; => foo: 1
(send~ o whatever 1) ; Unknown method whatever: (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:
Alternatively, we can use Swindle for a CLOS-like object system, and do something similar to the Common Lisp solution:
<lang racket>
<syntaxhighlight lang="racket">
#lang swindle
#lang swindle


Line 1,259: Line 1,259:
(foo "one")
(foo "one")
;; => No method in #<generic:foo> for "one"
;; => No method in #<generic:foo> for "one"
</syntaxhighlight>
</lang>


=={{header|Raku}}==
=={{header|Raku}}==
(formerly Perl 6)
(formerly Perl 6)
{{works with|Rakudo|2020.08.1}}
{{works with|Rakudo|2020.08.1}}
<lang perl6>class Farragut {
<syntaxhighlight lang="raku" line>class Farragut {
method FALLBACK ($name, *@rest) {
method FALLBACK ($name, *@rest) {
say "{self.WHAT.raku}: $name.tc() the @rest[], full speed ahead!";
say "{self.WHAT.raku}: $name.tc() the @rest[], full speed ahead!";
Line 1,273: Line 1,273:


Farragut.damn: 'torpedoes';
Farragut.damn: 'torpedoes';
Sparrow.hoist: <Jolly Roger mateys>;</lang>
Sparrow.hoist: <Jolly Roger mateys>;</syntaxhighlight>
{{out}}
{{out}}
<pre>Farragut: Damn the torpedoes, full speed ahead!
<pre>Farragut: Damn the torpedoes, full speed ahead!
Line 1,280: Line 1,280:
<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>.
<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>.


<lang perl6>class L-Value {
<syntaxhighlight lang="raku" line>class L-Value {
our $.value = 10;
our $.value = 10;
method FALLBACK($name, |c) is rw { $.value }
method FALLBACK($name, |c) is rw { $.value }
Line 1,288: Line 1,288:
say $l.any-odd-name; # 10
say $l.any-odd-name; # 10
$l.some-other-name = 42;
$l.some-other-name = 42;
say $l.i-dont-know; # 42</lang>
say $l.i-dont-know; # 42</syntaxhighlight>


=={{header|Ring}}==
=={{header|Ring}}==
<lang ring>
<syntaxhighlight lang="ring">
load "stdlibcore.ring"
load "stdlibcore.ring"


Line 1,312: Line 1,312:
call cMethodName()
call cMethodName()
ok
ok
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 1,323: Line 1,323:


=={{header|Ruby}}==
=={{header|Ruby}}==
<lang ruby>class Example
<syntaxhighlight lang="ruby">class Example
def foo
def foo
puts "this is foo"
puts "this is foo"
Line 1,344: Line 1,344:
example.grill # prints “tried to handle unknown method grill”
example.grill # prints “tried to handle unknown method grill”
example.ding("dong") # prints “tried to handle unknown method ding”
example.ding("dong") # prints “tried to handle unknown method ding”
# prints “it had arguments: ["dong"]”</lang>
# prints “it had arguments: ["dong"]”</syntaxhighlight>


=={{header|Scala}}==
=={{header|Scala}}==
{{works with|Scala|2.9}}
{{works with|Scala|2.9}}
As of scala 2.9, scalac must receive the -Xexperimental optional for Dynamic to receive this treatment.
As of scala 2.9, scalac must receive the -Xexperimental optional for Dynamic to receive this treatment.
<lang scala>class DynamicTest extends Dynamic
<syntaxhighlight lang="scala">class DynamicTest extends Dynamic
{
{
def foo()=println("this is foo")
def foo()=println("this is foo")
Line 1,369: Line 1,369:
}
}
}
}
</syntaxhighlight>
</lang>
Output:
Output:
<pre>this is foo
<pre>this is foo
Line 1,379: Line 1,379:
=={{header|Sidef}}==
=={{header|Sidef}}==
The special '''AUTOLOAD''' method gets called when a method isn't defined in the current class:
The special '''AUTOLOAD''' method gets called when a method isn't defined in the current class:
<lang ruby>class Example {
<syntaxhighlight lang="ruby">class Example {
method foo {
method foo {
say "this is foo"
say "this is foo"
Line 1,400: Line 1,400:
example.grill; # prints “tried to handle unknown method grill”
example.grill; # prints “tried to handle unknown method grill”
example.ding("dong"); # prints “tried to handle unknown method ding”
example.ding("dong"); # prints “tried to handle unknown method ding”
# prints “it had arguments: dong”</lang>
# prints “it had arguments: dong”</syntaxhighlight>


=={{header|Slate}}==
=={{header|Slate}}==
Line 1,406: Line 1,406:
Here is an example of unknown methods being used to call shell commands (this is already defined in the base image):
Here is an example of unknown methods being used to call shell commands (this is already defined in the base image):


<lang slate>define: #shell &builder: [lobby newSubSpace].
<syntaxhighlight lang="slate">define: #shell &builder: [lobby newSubSpace].


_@shell didNotUnderstand: message at: position
_@shell didNotUnderstand: message at: position
Line 1,429: Line 1,429:
ifFalse: [args do: [| :arg | command ; ' ' ; arg]]]]] writingAs: String)
ifFalse: [args do: [| :arg | command ; ' ' ; arg]]]]] writingAs: String)
ifNil: [resend] ifNotNilDo: [| :cmd | [Platform run: cmd]]]
ifNil: [resend] ifNotNilDo: [| :cmd | [Platform run: cmd]]]
].</lang>
].</syntaxhighlight>


Here is an example of it being used:
Here is an example of it being used:


<lang slate>slate[1]> shell ls: '*.image'.
<syntaxhighlight lang="slate">slate[1]> shell ls: '*.image'.
kernel.new.little.64.1244260494374694.image slate2.image
kernel.new.little.64.1244260494374694.image slate2.image
net.image slate.image
net.image slate.image
True
True
slate[2]></lang>
slate[2]></syntaxhighlight>


=={{header|Smalltalk}}==
=={{header|Smalltalk}}==
{{works with|GNU Smalltalk}}
{{works with|GNU Smalltalk}}


<lang smalltalk>Object subclass: CatchThemAll [
<syntaxhighlight lang="smalltalk">Object subclass: CatchThemAll [
foo [ 'foo received' displayNl ]
foo [ 'foo received' displayNl ]


Line 1,459: Line 1,459:
a bar.
a bar.
a weCanDoIt.
a weCanDoIt.
a theyCanToo: 'eat' and: 'walk'.</lang>
a theyCanToo: 'eat' and: 'walk'.</syntaxhighlight>


There are two ways to catch unimplemented messages:
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 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:
* on the sender side, by catching the MessageNotUnderstood exception, as follows:
<lang smalltalk>[
<syntaxhighlight lang="smalltalk">[
bla := someObject fooBar.
bla := someObject fooBar.
foo := bla.
foo := bla.
] on: MessageNotUnderstood do:[:ex |
] on: MessageNotUnderstood do:[:ex |
ex return: 'fortyTwo'
ex return: 'fortyTwo'
]</lang>
]</syntaxhighlight>
this will leave 'fortyTwo' on bla AND foo (because the handler proceeds).
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).
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,475: Line 1,475:
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.
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:
We can check for this in the handler, by checking for which message got us there:
<lang smalltalk>[
<syntaxhighlight lang="smalltalk">[
bla := someObject fooBar.
bla := someObject fooBar.
foo := bla.
foo := bla.
Line 1,485: Line 1,485:
ex reject
ex reject
]
]
]</lang>
]</syntaxhighlight>
the reject will re-reaise the exception, and lead us to an outer handler, or the debugger, if there is none.
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}}
{{works with|Smalltalk/X}}
There is a utility method for exactly the above (it catches only #fooBar to the original receiver):
There is a utility method for exactly the above (it catches only #fooBar to the original receiver):
<lang smalltalk>anObject perform:#fooBar ifNotUnderstood:[ ...some alternative code and return value... ].</lang>
<syntaxhighlight lang="smalltalk">anObject perform:#fooBar ifNotUnderstood:[ ...some alternative code and return value... ].</syntaxhighlight>


=={{header|SuperCollider}}==
=={{header|SuperCollider}}==
<lang SuperCollider>Ingorabilis {
<syntaxhighlight lang="supercollider">Ingorabilis {


tell {
tell {
Line 1,511: Line 1,511:


}
}
</syntaxhighlight>
</lang>
Usage:
Usage:


<syntaxhighlight lang="supercollider">
<lang SuperCollider>
i = Ingorabilis.new;
i = Ingorabilis.new;
i.tell; // prints "I told you so"
i.tell; // prints "I told you so"
i.find; // prints ""I found nothing"
i.find; // prints ""I found nothing"
i.think(1, 3, 4, 7);
i.think(1, 3, 4, 7);
</syntaxhighlight>
</lang>


The latter answers:
The latter answers:
<lang SuperCollider>Method selector 'think' not understood by Ingorabilis
<syntaxhighlight lang="supercollider">Method selector 'think' not understood by Ingorabilis
Giving you some good arguments in the following
Giving you some good arguments in the following
1
1
Line 1,534: Line 1,534:
instance variables [0]
instance variables [0]
}
}
<...></lang>
<...></syntaxhighlight>
Catch the method call:
Catch the method call:
<syntaxhighlight lang="supercollider">
<lang SuperCollider>
i = Ingorabilis.new
i = Ingorabilis.new
try { i.think } { "We are not delegating to super, because I don't want it".postln };
try { i.think } { "We are not delegating to super, because I don't want it".postln };
</syntaxhighlight>
</lang>


=={{header|Tcl}}==
=={{header|Tcl}}==
{{works with|Tcl|8.6}} or {{libheader|TclOO}}
{{works with|Tcl|8.6}} or {{libheader|TclOO}}
<lang tcl>package require TclOO
<syntaxhighlight lang="tcl">package require TclOO
# First create a simple, conventional class and object
# First create a simple, conventional class and object
oo::class create Example {
oo::class create Example {
Line 1,570: Line 1,570:
example grill; # prints “tried to handle unknown method "grill"”
example grill; # prints “tried to handle unknown method "grill"”
example ding dong; # prints “tried to handle unknown method "ding"”
example ding dong; # prints “tried to handle unknown method "ding"”
# prints “it had arguments: dong”</lang>
# prints “it had arguments: dong”</syntaxhighlight>


=={{header|UNIX Shell}}==
=={{header|UNIX Shell}}==
{{works with|Bash}}
{{works with|Bash}}
bash doesn't have objects with methods, but it can handle unknown commands:
bash doesn't have objects with methods, but it can handle unknown commands:
<lang Bash>function handle_error {
<syntaxhighlight lang="bash">function handle_error {
status=$?
status=$?


Line 1,591: Line 1,591:


# Trap errors.
# Trap errors.
trap 'handle_error' ERR</lang>
trap 'handle_error' ERR</syntaxhighlight>
Sample usage:
Sample usage:
$ foo
$ foo
Line 1,599: Line 1,599:
=={{header|Wren}}==
=={{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.
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.
<lang ecmascript>import "io" for Stdin, Stdout
<syntaxhighlight lang="ecmascript">import "io" for Stdin, Stdout


class Test {
class Test {
Line 1,634: Line 1,634:
}
}
}
}
System.print("OK, continuing.")</lang>
System.print("OK, continuing.")</syntaxhighlight>


{{out}}
{{out}}
Line 1,658: Line 1,658:
=={{header|zkl}}==
=={{header|zkl}}==
If something can not be resolved (in a class) the function __notFound is called. It can redirect to another object.
If something can not be resolved (in a class) the function __notFound is called. It can redirect to another object.
<lang zkl>class C{ fcn __notFound(name){println(name," not in ",self); bar}
<syntaxhighlight lang="zkl">class C{ fcn __notFound(name){println(name," not in ",self); bar}
fcn bar{vm.arglist.println("***")}
fcn bar{vm.arglist.println("***")}
}</lang>
}</syntaxhighlight>
<pre>
<pre>
C.foo //-->"foo not in Class(C)", returns Fcn(bar)
C.foo //-->"foo not in Class(C)", returns Fcn(bar)