Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Re: Re: Object Terminology (and an awful shaggy dog story)

by stvn (Monsignor)
on Jan 12, 2004 at 17:53 UTC ( [id://320710]=note: print w/replies, xml ) Need Help??


in reply to Re: Object Terminology (and an awful shaggy dog story)
in thread Object Terminology

Ovid,

Exploding Tigers. Nice, although you might get some slack from PETA for it. :)

While I agree with all your points (for the most part). I still love my multiple-inheritance. Eiffel provides a handy way to handle some of those name conflicts you speak of, by allowing you to rename methods (among other things). Now Eiffel forces you to adjust your methods to the renamed method. In perl though, this is not nessecary. I submit the following code:

# assume that these 2 methods are # defined in some module and then # exported into your classes's # package namespace. sub redefines ($$$) { no strict 'refs'; no warnings 'redefine'; my ($package, $old_name, $new_name) = @_; my ($caller_package) = caller(); $caller_package->isa($package) || die "Can't rename from a package you do not inherit from"; my $old_method = $package->can($old_name); (defined($old_method)) || die "you cannot rename a method you dont have"; my $current_method; if (exists ${"${caller_package}::"}{$old_name}) { $current_method = \&{"${caller_package}::$old_name"}; } else { $current_method = sub { die "Method no implemented" } } *{"${caller_package}::$old_name"} = sub { my $self = shift; my ($_caller_package) = caller(); return $self->$new_name(@_) if ($package->isa($_caller_package)); # or $self->$current_method(@_); }; *{"${caller_package}::$new_name"} = $old_method; } sub next_method { my ($self, $package, @args) = @_; my ($p, $f, $l, $function) = caller(1); $self->isa($package) || die "Can only dispatch on ancestors of $p"; my @module_path = split /\:\:/, $function; my $caller_function = $module_path[-1]; my $dispatch = $package->can($caller_function); return $self->$dispatch(@args); }
Your Exploding Tiger can then be implemented as such.
use strict; use warnings; package ExplodingTiger; ## import the 2 functions above somehow @ExplodingTiger::ISA = qw(Tiger Bomb); redefines("Tiger", "explode", "spontaneouslyCombust"); sub new { my ($class) = @_; my $exploding_tiger = { bomb_type => "Bomb" }; return bless($exploding_tiger, ref($class) || $class); } sub explode { my ($self, @args) = @_; print "ROAR!!! I'm an exploding Tiger!\n"; $self->next_method($self->{bomb_type}, @args); } 1;

See my scratchpad for a complete runnable example.

Your delegation solution neglected to allow for the original spontaneous combustion behavior to still remain around. It gets redefined in ExplodingTiger::explode. Also, you are faced with the problem that if code from your inherited Tiger class uses the explode method anywhere for a specific purpose it will dispatch to the ExplodingTiger::explode method instead, and the behavior of the Bomb::explode method it delegates too may not be appropriate. The above solution will account for that (see the scratchpad example for the details). It also allows for you to inherit other Bomb methods without needing to delegate.

Another benefit of delegation is that you are relying only on the published implementation. With inheritance, you must comply explicitly with the inherited implementation ...
I am not 100% sure i understand what you are saying here. I assume you are saying that you must deal with the fact a class is inherited, and that is part of the implementation? If that is not what you are saying then disregard the rant that follows, if it is what you are saying, then ...

I believe this is not an issue of inheritance as a concept, but in the implementation of various documentation tools (javadoc, I curse thee!!!).

In Eiffel, there are 2 "views" of a class available in the documentation. A view of the methods implemented by the class directly, and a "flattened" view of all the methods available from the class (all implemented and all inherited).

I believe this takes the OO idea of encapsulation to its next level. In encapsulating inheritance information as well. I mean after all you are supposed to encapsulate/hide the implementation in OOP, and is not inheritance part of a classes implementation?

-stvn

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://320710]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (6)
As of 2024-03-29 14:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found