Respond to an unknown method call: Difference between revisions
(add E example) |
(added ruby and perl) |
||
Line 20: | Line 20: | ||
} |
} |
||
}</lang> |
}</lang> |
||
=={{header|Perl}}== |
|||
<lang perl>package Example; |
|||
sub new { |
|||
bless {} |
|||
} |
|||
sub foo { |
|||
print "this is foo\n"; |
|||
} |
|||
sub bar { |
|||
print "this is bar\n"; |
|||
} |
|||
sub AUTOLOAD { |
|||
my $name = $AUTOLOAD; |
|||
my ($self, @args) = @_; |
|||
print "tried to handle unknown method $name\n"; |
|||
if (@args) { |
|||
print "it had arguments: @args\n"; |
|||
} |
|||
} |
|||
1; |
|||
package main; |
|||
my $example = Example->new; |
|||
$example->foo; # prints “this is foo” |
|||
$example->bar; # prints “this is bar” |
|||
$example->grill; # prints “tried to handle unknown method Example::grill” |
|||
$example->ding("dong"); # prints “tried to handle unknown method Example::ding” |
|||
# prints “it had arguments: dong” |
|||
# prints “tried to handle unknown method Example::DESTROY” <- I don't know why it does this</lang> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
Line 42: | Line 73: | ||
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',)”</lang> |
||
=={{header|Ruby}}== |
|||
<lang ruby>class Example |
|||
def foo |
|||
puts "this is foo" |
|||
end |
|||
def bar |
|||
puts "this is bar" |
|||
end |
|||
def method_missing(name, *args) |
|||
puts "tried to handle unknown method %s" % name # name is a symbol |
|||
unless args.empty? |
|||
puts "it had arguments: %p" % [args] |
|||
end |
|||
end |
|||
end |
|||
example = Example.new |
|||
example.foo # prints “this is foo” |
|||
example.bar # prints “this is bar” |
|||
example.grill # prints “tried to handle unknown method grill” |
|||
example.ding("dong") # prints “tried to handle unknown method ding” |
|||
# prints “it had arguments: ["dong"]”</lang> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
Revision as of 07:27, 4 June 2009
You are encouraged to solve this task according to the task description, using any language you may know.
Demonstrate how to make the object respond (sensibly/usefully) to an invocation of a method on it that it does not support through its class definitions. Note that this is not the same as just invoking a defined method whose name is given dynamically; the method named at the point of invocation must not be defined.
This task is intended only for object systems that use a dynamic dispatch mechanism.
E
In E, a message consists of a verb (arbitrary string) and arguments (sequence of arbitrary objects). It is conceptually entirely up to any given object how it dispatches incoming messages.
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 {
to foo() { println("this is foo") } to bar() { println("this is bar") } match [verb, args] { println(`got unrecognized message $verb`) if (args.size() > 0) { println(`it had arguments: $args`) } }
}</lang>
Perl
<lang perl>package Example; sub new {
bless {}
} sub foo {
print "this is foo\n";
} sub bar {
print "this is bar\n";
} sub AUTOLOAD {
my $name = $AUTOLOAD; my ($self, @args) = @_; print "tried to handle unknown method $name\n"; if (@args) { print "it had arguments: @args\n"; }
} 1;
package main; my $example = Example->new;
$example->foo; # prints “this is foo” $example->bar; # prints “this is bar” $example->grill; # prints “tried to handle unknown method Example::grill” $example->ding("dong"); # prints “tried to handle unknown method Example::ding”
# prints “it had arguments: dong” # prints “tried to handle unknown method Example::DESTROY” <- I don't know why it does this</lang>
Python
Python objects can implement a __getattr__()
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:
def foo(self): print "this is foo" def bar(self): print "this is bar" def __getattr__(self, name): def method(*args): print "tried to handle unknown method " + name if args: print "it had arguments: " + str(args) return method
example = Example()
example.foo() # prints “this is foo” example.bar() # prints “this is bar” example.grill() # prints “tried to handle unknown method grill” example.ding("dong") # prints “tried to handle unknown method ding”
# prints “it had arguments: ('dong',)”</lang>
Ruby
<lang ruby>class Example
def foo puts "this is foo" end def bar puts "this is bar" end def method_missing(name, *args) puts "tried to handle unknown method %s" % name # name is a symbol unless args.empty? puts "it had arguments: %p" % [args] end end
end
example = Example.new
example.foo # prints “this is foo” example.bar # prints “this is bar” example.grill # prints “tried to handle unknown method grill” example.ding("dong") # prints “tried to handle unknown method ding”
# prints “it had arguments: ["dong"]”</lang>
Tcl
<lang tcl># First create a simple, conventional class and object oo::class create Example {
method foo {} { puts "this is foo" } method bar {} { puts "this is bar" }
} Example create example
- Modify the object to have a custom ‘unknown method’ interceptor
oo::objdefine example {
method unknown {name args} { puts "tried to handle unknown method \"$name\"" if {[llength $args]} { puts "it had arguments: $args" } }
}
- Show off what we can now do...
example foo; # prints “this is foo” example bar; # prints “this is bar” example grill; # prints “tried to handle unknown method "grill"” example ding dong; # prints “tried to handle unknown method "ding"”
# prints “it had arguments: dong”</lang>