⚠️ Warning: This is a draft ⚠️
This means it might contain formatting issues, incorrect code, conceptual problems, or other severe issues.
If you want to help to improve and eventually enable this page, please fork RosettaGit's repository and open a merge request on GitHub.
{{task|Object oriented}}
;Task: Invoke an object method where the name of the method to be invoked can be generated at run time.
;Related tasks:
- [[Respond to an unknown method call]].
- [[Runtime evaluation]]
AutoHotkey
This object has 3 methods, and asks the user to name one to call. Instead of using Func(), one could use a class definition.
obj := {mA: Func("mA"), mB: Func("mB"), mC: Func("mC")}
InputBox, methodToCall, , Which method should I call?
obj[methodToCall].()
mA(){
MsgBox Method A
}
mB(){
MsgBox Method B
}
mC(){
MsgBox Method C
}
Bracmat
(task=
( oracle
= (predicate="is made of green cheese")
(generateTruth=.str$(!arg " " !(its.predicate) "."))
(generateLie=.str$(!arg " " !(its.predicate) "!"))
)
& new$oracle:?SourceOfKnowledge
& put
$ "You may ask the Source of Eternal Wisdom ONE thing.
Enter \"Truth\" or \"Lie\" on the next line and press the <Enter> key.
"
& whl
' ( get':?trueorlie:~Truth:~Lie
& put$"Try again\n"
)
& put$(str$("You want a " !trueorlie ". About what?" \n))
& get'(,STR):?something
& (SourceOfKnowledge..str$(generate !trueorlie))$!something
);
{{out|Example}}
{?} !task
You may ask the Source of Eternal Wisdom ONE thing.
Enter "Truth" or "Lie" on the next line and press the <Enter> key.
"Lie"
You want a Lie. About what?
The sea
{!} The sea is made of green cheese!
C#
using System; class Example { public int foo(int x) { return 42 + x; } } class Program { static void Main(string[] args) { var example = new Example(); var method = "foo"; var result = (int)example.GetType().GetMethod(method).Invoke(example, new object[]{ 5 }); Console.WriteLine("{0}(5) = {1}", method, result); } }
{{out}} foo(5) = 47
=={{header|Caché ObjectScript}}==
$METHOD executes a named instance method for a specified instance of a designated class.
Class Unknown.Example Extends %RegisteredObject
{
Method Foo()
{
Write "This is foo", !
}
Method Bar()
{
Write "This is bar", !
}
}
{{out|Examples}}
USER>Set obj=##class(Unknown.Example).%New()
USER>Do $Method(obj, "Foo")
This is foo
USER>Do $Method(obj, "Bar")
This is bar
Common Lisp
Unknown methods are called just like any other function. Find the method-naming symbol using INTERN then call it with FUNCALL.
(funcall (intern "SOME-METHOD") my-object a few arguments)
=={{header|Déjà Vu}}==
local :object { :add @+ }
local :method :add
!. object! method 1 2
{{out}}
3
E
This example goes well with the object named example
in [[Respond to an unknown method call#E]].
for name in ["foo", "bar"] {
E.call(example, name, [])
}
Elena
ELENA 4.1 :
import extensions;
class Example
{
foo(x)
= x + 42;
}
public program()
{
var example := new Example();
var methodSignature := "foo";
var invoker := new MessageName(methodSignature);
var result := invoker(example,5);
console.printLine(methodSignature,"(",5,") = ",result)
}
{{out}}
foo(5) = 47
Factor
Factor's object model is such that objects themselves don't contain methods — generic words do. So there is nothing different about invoking an unknown method than invoking an unknown word in general.
USING: accessors kernel math prettyprint sequences words ;
IN: rosetta-code.unknown-method-call
TUPLE: foo num ;
C: <foo> foo
GENERIC: add5 ( x -- y )
M: foo add5 num>> 5 + ;
42 <foo> ! construct a foo
"add" "5" append ! construct a word name
! must specify vocab to look up a word
"rosetta-code.unknown-method-call"
lookup-word execute . ! 47
Forth
{{works with|Forth}} Works with any ANS Forth
Needs the FMS-SI (single inheritance) library code located here: http://soton.mpeforth.com/flag/fms/index.html
include FMS-SI.f
include FMS-SILib.f
var x \ instantiate a class var object named x
\ Use a standard Forth string and evaluate it.
\ This is equivalent to sending the !: message to object x
42 x s" !:" evaluate
x p: 42 \ send the print message ( p: ) to x to verify the contents
Go
package main import ( "fmt" "reflect" ) type example struct{} // the method must be exported to be accessed through reflection. func (example) Foo() int { return 42 } func main() { // create an object with a method var e example // get the method by name m := reflect.ValueOf(e).MethodByName("Foo") // call the method with no argments r := m.Call(nil) // interpret first return value as int fmt.Println(r[0].Int()) // => 42 }
Groovy
class Example {
def foo(value) {
"Invoked with '$value'"
}
}
def example = new Example()
def method = "foo"
def arg = "test value"
assert "Invoked with 'test value'" == example."$method"(arg)
==Icon and {{header|Unicon}}==
procedure main()
x := foo() # create object
x.m1() # static call of m1 method
# two examples where the method string can be dynamically constructed ...
"foo_m1"(x) # ... need to know class name and method name to construct name
x.__m["m1"] # ... general method (better)
end
class foo(a,b,c) # define object
method m1(x)
end
end
For more information on this see [[Respond_to_an_unknown_method_call#Icon_and_Unicon|Respond to an unknown method call]].
Io
String literal "foo" may be replaced by any expression resulting in a string.
Example := Object clone
Example foo := method(x, 42+x)
name := "foo"
Example clone perform(name,5) println // prints "47"
J
'''Solution''': There are multiple ways to evoke code at runtime. The most common is '''". y''' (''eval''uate the code in the string y, producing a noun), but there's also 'name'~ (which will modify J's stack by replacing the two tokens ''''name'''' and ~ with the named object) as well as '''x 128!:2 y''' (''apply'' the verb described by x to the noun y).
There are other methods as well, e.g., '''@.''','''`:''', and '''^:''', though these are designed to consume gerunds (pre-parsed ASTs) rather than strings (though, of course, a pre-processor can always be provided to convert strings into ASTs before feeding them to these operators).
'''Example''':
sum =: +/
prod =: */
count =: #
nameToDispatch =: 'sum' NB. pick a name already defined
". nameToDispatch,' 1 2 3'
6
nameToDispatch~ 1 2 3
6
nameToDispatch (128!:2) 1 2 3
6
nameToDispatch =: 'count' NB. pick another name
". nameToDispatch,' 1 2 3'
3
nameToDispatch~ 1 2 3
3
nameToDispatch (128!:2) 1 2 3
3
Java
Using reflection
import java.lang.reflect.Method; class Example { public int foo(int x) { return 42 + x; } } public class Main { public static void main(String[] args) throws Exception { Object example = new Example(); String name = "foo"; Class<?> clazz = example.getClass(); Method meth = clazz.getMethod(name, int.class); Object result = meth.invoke(example, 5); // result is int wrapped in an object (Integer) System.out.println(result); // prints "47" } }
JavaScript
String literal "foo" may be replaced by any expression resulting in a string
example = new Object; example.foo = function(x) { return 42 + x; }; name = "foo"; example[name](5) # => 47
Julia
{{works with|Julia|0.6}}
const functions = Dict{String,Function}( "foo" => x -> 42 + x, "bar" => x -> 42 * x) @show functions["foo"](3) @show functions["bar"](3)
{{out}}
(functions["foo"])(3) = 45
(functions["bar"])(3) = 126
Kotlin
When you try to compile the following program, it will appear to the compiler that the local variable 'c' is assigned but never used and a warning will be issued accordingly. You can get rid of this warning by compiling using the -nowarn flag.
// Kotlin JS version 1.1.4-3 class C { fun foo() { println("foo called") } } fun main(args: Array<String>) { val c = C() val f = "c.foo" js(f)() // invokes c.foo dynamically }
{{out}}
foo called
Lasso
type {
public foo() => {
return 'foo was called'
}
public bar() => {
return 'this time is was bar'
}
}
local(obj = mytype, methodname = tag('foo'), methodname2 = tag('bar'))
#obj->\#methodname->invoke
#obj->\#methodname2->invoke
{{out}}
foo was called
this time is was bar
Lingo
obj = script("MyClass").new()
-- ...
method = #foo
arg1 = 23
res = call(method, obj, arg1)
Logtalk
For this task, we first define a simple object with a single method:
:- object(foo).
:- public(bar/1).
bar(42).
:- end_object.
Second, we define another object that asks the user for a message to be sent to the first object:
:- object(query_foo).
:- public(query/0).
query :-
write('Message: '),
read(Message),
foo::Message.
write('Reply: '),
write(Message), nl.
:- end_object.
After compiling and loading both objects, we can try: | ?- query_foo::query. Message: bar(X). Reply: bar(42)
Lua
Don't forget to pass the object for methods!
local example = { } function example:foo (x) return 42 + x end local name = "foo" example[name](example, 5) --> 47
Mathematica
Creates a dialog box where one can type a function (Sin, Cos, Tan ...) and then a second dialog box for a value.
{{out}}
```txt
Input: Sin
Input: 3.1415
Output: 0.0000926536
=={{header|MATLAB}} / {{header|Octave}}==
funName = 'foo'; % generate function name feval (funNAME, ...) % evaluation function with optional parameters funName = 'a=atan(pi)'; % generate function name eval (funName, 'printf(''Error\n'')')
=={{header|Objective-C}}==
@interface Example : NSObject
- (NSNumber *)foo;
@end
@implementation Example
- (NSNumber *)foo {
return @42;
}
@end
int main (int argc, const char *argv[]) {
@autoreleasepool {
id example = [[Example alloc] init];
SEL selector = @selector(foo); // or = NSSelectorFromString(@"foo");
NSLog(@"%@", [example performSelector:selector]);
}
return 0;
}
The performSelector: ...
methods can only be used with methods with 0 - 2 object arguments, and an object or void
return type. For all other calls, one can create an NSInvocation
object and invoke it, or directly call one of the objc_msgSend
family of runtime functions.
Oforth
A method object can be retrieved from its name using asMethod.
16 "sqrt" asMethod perform
Others : asFuntion : retrieve a function asClass : retrieve a class asProperty : retrieve a property
A generic way to search a word into the dictionary in to use find method :
16 "sqrt" Word find perform
PARI/GP
foo()=5;
eval(Str("foo","()"))
Perl
package Example; sub new { bless {} } sub foo { my ($self, $x) = @_; return 42 + $x; } package main; my $name = "foo"; print Example->new->$name(5), "\n"; # prints "47"
Perl 6
Just for the fun of it, we'll mix in an anonymous role into an integer instead of defining a class.
my $object = 42 but role { method add-me($x) { self + $x } }
my $name = 'add-me';
say $object."$name"(5); # 47
The double quotes are required, by the way; without them the variable would be interpreted as a hard ref to a method.
Phix
Not specifically anything to do with objects, but you can construct routine names at runtime:
procedure Hello()
?"Hello"
end procedure
string erm = "Hemmm"
for i=3 to 5 do
erm[i]+=-1+(i=5)*3
end for
call_proc(routine_id(erm),{})
PHP
<?php class Example { function foo($x) { return 42 + $x; } } $example = new Example(); $name = 'foo'; echo $example->$name(5), "\n"; // prints "47" // alternately: echo call_user_func(array($example, $name), 5), "\n"; ?>
PicoLisp
This can be done with the '[http://software-lab.de/doc/refS.html#send send]' function.
(send (expression) Obj arg1 arg2)
Pike
with [] instead of -> a string can be used to name a method:
string unknown = "format_nice";
object now = Calendar.now();
now[unknown]();
PowerShell
A random method using a random number:
$method = ([Math] | Get-Member -MemberType Method -Static | Where-Object {$_.Definition.Split(',').Count -eq 1} | Get-Random).Name $number = (1..9 | Get-Random) / 10 $result = [Math]::$method($number) $output = [PSCustomObject]@{ Method = $method Number = $number Result = $result } $output | Format-List
{{Out}}
Method : Atan
Number : 0.5
Result : 0.463647609000806
Python
String literal "foo" may be replaced by any expression resulting in a string
class Example(object): def foo(self, x): return 42 + x name = "foo" getattr(Example(), name)(5) # => 47
Qi
(define foo -> 5)
(define execute-function
Name -> (eval [(INTERN Name)]))
(execute-function "foo")
Racket
#lang racket
(define greeter
(new (class object% (super-new)
(define/public (hello name)
(displayln (~a "Hello " name "."))))))
; normal method call
(send greeter hello "World")
; sending an unknown method
(define unknown 'hello)
(dynamic-send greeter unknown "World")
Ruby
You may replace :foo, :bar or "bar" with any expression that returns a Symbol or String.
class Example def foo 42 end def bar(arg1, arg2, &block) block.call arg1, arg2 end end symbol = :foo Example.new.send symbol # => 42 Example.new.send( :bar, 1, 2 ) { |x,y| x+y } # => 3 args = [1, 2] Example.new.send( "bar", *args ) { |x,y| x+y } # => 3
Object#send can also call protected and private methods, skipping the usual access checks. Ruby 1.9 adds Object#public_send, which only calls public methods.
{{works with|Ruby|1.9}}
class Example private def privacy; "secret"; end public def publicity; "hi"; end end e = Example.new e.public_send :publicity # => "hi" e.public_send :privacy # raises NoMethodError e.send :privacy # => "secret"
Scala
{{libheader|Scala}}
class Example { def foo(x: Int): Int = 42 + x } object Main extends App { val example = new Example val meth = example.getClass.getMethod("foo", classOf[Int]) assert(meth.invoke(example, 5.asInstanceOf[AnyRef]) == 47.asInstanceOf[AnyRef], "Not confirm expectation.") println(s"Successfully completed without errors. [total ${scala.compat.Platform.currentTime - executionStart} ms]") }
Sidef
class Example { method foo(x) { 42 + x } } var name = 'foo' var obj = Example() say obj.(name)(5) # prints: 47 say obj.method(name)(5) # =//=
Smalltalk
Object subclass: #Example.
Example extend [
foo: x [
^ 42 + x ] ].
symbol := 'foo:' asSymbol. " same as symbol := #foo: "
Example new perform: symbol with: 5. " returns 47 "
The perform:with:with:
family of methods exist for methods with 0 - 2 (3 in [[GNU Smalltalk]]) arguments. For methods with more arguments, use perform:withArguments:
, which takes an array of arguments.
Tcl
Method names are really just strings, i.e., ordinary values that can be produced by any mechanism:
package require Tcl 8.6 oo::class create Example { method foo {} {return 42} method 1 {s} {puts "fee$s"} method 2 {s} {puts "fie$s"} method 3 {s} {puts "foe$s"} method 4 {s} {puts "fum$s"} } set eg [Example new] set mthd [format "%c%c%c" 102 111 111]; # A "foo" by any other means would smell as sweet puts [$eg $mthd] for {set i 1} {$i <= 4} {incr i} { $eg $i ... }
{{out|The above produces this output}} 42 fee... fie... foe... fum...
zkl
name:="len"; "this is a test".resolve(name)() //-->14
{{omit from|Ada}} {{omit from|Axe}} {{omit from|BASIC}} {{omit from|C|No such thing as object method}} {{omit from|GUISS}} {{omit from|Rust|No runtime reflection}} {{omit from|ZX Spectrum Basic}}