Re: Invoking method in another package
by diotalevi (Canon) on Sep 30, 2002 at 00:23 UTC
|
Your usage is... unusual and not good design if you're just trying to do the typical object inheritance thing. Here I've altered your code to have meaningful package names, Cow inherits from Animal and the object variables make more sense for something that might be polymorphic later (cow became sound). If you had other animals you would just put the right data into the right variables and then rooster's could cluck. I added a roster class since it was trivial once the variables were changed around. Now if you *weren't* looking for polymorphic inheritance then speak up since that's what it looks like you're getting at.
my $fb = new Cow;
$fb->sound;
package Rooster;
use base 'Animal';
sub new
{
bless { animal_type => 'rooster',
sound => 'cluck' }, shift
}
package Cow;
use base 'Animal';
sub new
{
bless { animal_type => 'cow',
sound => 'moo' }, shift
}
package Animal;
sub sound
{
my $self = shift;
print $self->{animal_type} . "s go: " . $self->{sound};
}
| [reply] [d/l] |
|
What I'm trying to do is just pass the blessed hash reference along to Barfoo::thisone so I can rip values from it. Maybe I'm just better off using global variables :|
| [reply] [d/l] |
|
Oh ok, I can understand that. I've been writing code in a similar vein except mine steals lexical variables. If you want to steal variables out of a blessed something then what you originally wrote is perfectly fine - you might want to see about importing that thisone() method or name it something that indicates it's integrity violating nature. So what your call to Foobar::thisone($obj) is semantically equivalent to thisone($obj) except that one version leaves the method off in the original package. If you look at my signature you'll see an example of a something being violated in the exact same way. I leave the B::svref_2object method over there since I didn't feel like importing it into the current scope. At that point it becomes preference and style.
| [reply] [d/l] [select] |
Re: Invoking method in another package
by chromatic (Archbishop) on Sep 30, 2002 at 00:18 UTC
|
If I had to do something of the sort, I'd rather write:
Barfoo::thisone( $fb );
It's a little more explicit that I'm treating a method as a regular function. I've only ever done this in tests, where I'm passing a mock object to the method I want to test.
In your case, I would call it a mistake. thisone() doesn't really look like an object method. I'd make it into a class method (or just a normal function) and skip the method-looking invocation.
| [reply] [d/l] |
Re: Invoking method in another package
by Dog and Pony (Priest) on Sep 30, 2002 at 09:17 UTC
|
It is essentially equal to:
Barfoo::thisone($fb);
Changing the call to that, and changing the name of the variable $self to something like $object won't change anything, but will make the code more readable, as well as making your intent more clear.
To me it seems you want a class method (as opposed to object method), or call it a function, that gets some information out of an object.
Does it need to be a real object at all? A hashref
$fb = { cow => 'moo' };
would give the same result if you don't need more stuff (like methods) inside Foobar.
You have moved into a dark place.
It is pitch black. You are likely to be eaten by a grue. | [reply] [d/l] [select] |
Re: Invoking method in another package
by Steve_p (Priest) on Sep 30, 2002 at 03:30 UTC
|
There isn't anything wrong with it technically, but there are some style issues here. You are essentially using a Barfoo class as a temporary variable for the Foobar class, and then calling a function within that class. This is not that unusual within other Object Oriented languages, but because of the weird syntax to do it within Perl, its probably not the best thing to do. I think chromatic's suggestions above is probable the best way to do it.
| [reply] |
Re: Invoking method in another package
by rir (Vicar) on Sep 30, 2002 at 04:30 UTC
|
The real trick is that you might not invoke the method
in that Barfoo package.
The super classes of the specified class, Barfoo, may
be searched for the method even though it is unrelated
to the calling object's class.
If you just want to pass the hash as data, just pass it as the
first
parameter. | [reply] |
Re: Invoking method in another package
by perrin (Chancellor) on Sep 30, 2002 at 13:57 UTC
|
It is legal. It means "look for this method in the Barfoo class rather than the Foobar class". It's almost always the wrong thing to do. It's more likely you wanted to do this:
Barfoo->thisone($fb);
Note that this is class method and this the class name is the first parameter. | [reply] [d/l] |
Re: Invoking method in another package
by pdcawley (Hermit) on Sep 30, 2002 at 21:45 UTC
|
Yes, it works. No, it isn't any slower than normal OO dispatch. But it isn't necessarily advisable.
That said, it does have its uses. For instance, in a system I'm working on we have a set of methods that we need to be able to call on any object, and which can and should be overridden where necessary in client software. There's another set of methods that need to be callable on any object that should be considered as 'final'; in other words, we don't want client code overriding them.
To do this, we take advantage of the way perl will allow you to call fully qualified packages. Our overrideable methods all get put in UNIVERSAL, with a px_ prefix to prevent method name collisions with other objects, and methods that we need to be final get put into a PIXIE::* package.
Why do this? Because we want to maintain uniform access to methods. We could just make subroutine calls on objects for the 'final' methods and method calls for those methods in UNIVERSAL but we took the view that we wanted to maintain OO calling style. If the method calling overhead proves to be a significant issue when we come to do profiling, then of course we'll look at switching to direct function calls, but for now we'll stick with method calls throughout.
Note too that we're careful, in writing our PIXIE::* methods to make them dependent only on other PIXIE::* and px_* methods, and not to go making assumptions about the internal structure of objects on which they are called. | [reply] |
Re: Invoking method in another package
by bart (Canon) on Sep 30, 2002 at 20:26 UTC
|
In a standard situation is there anything wrong (slow, etc) with the following:
my $fb = new Foobar;
$fb->Barfoo::thisone;
I can imaging why it works. It is, IMO, only intended to call a SUPER method in case you have multiple inheritance, thus more than one parent in @ISA, and where more than one parent class have a thisone method. This way, you can specify which parent class you want to invoke the sub from.
This is all pretty low level. I would accept it as a hack (still better than leaving these things up to chance, I suppose), in the code that implements the class Foobar, but not in normal user code, which merely uses Foobar.
| [reply] [d/l] |