Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re: •Re: It's a dog, but what kind? (polymorphism , in Perl OO)

by flyingmoose (Priest)
on Mar 23, 2004 at 20:49 UTC ( #339182=note: print w/ replies, xml ) Need Help??


in reply to •Re: It's a dog, but what kind? (polymorphism , in Perl OO)
in thread It's a dog, but what kind? (polymorphism , in Perl OO)

eval " use $breed; " ;

Also, in true merlyn fashion, it looks like eval in this string context makes you have unsafe doggies if you are using your dogs on a web site and allowing input of the doggie type in a text field.

$dog = ' strict; doEvil(); ';

I also think the strange use of dog as a factory class to produce subtypes of dogs is a little odd-form from an OO form, and that most OO purists would frown on the eval and use of reflection to pick subclasses. But I come from a very non-Perlish OO background, so this is just my two cents.

In conclusion, if we want to call this a tutorial, I say this should be a tutorial on the factory pattern, not a tutorial on polymorphism. Polymorphism is a much more general concept, and we skip over that generality by starting with the factory piece first. I would be interested to see if the factory could be made without using eval, as well...I think it can, especially if the dogs were loaded previously in a more-safe matter. But hey, maybe we don't have to worry about unsafe loading of doggies -- they do allright in the back of a pickup truck usually :)

Anyway, cool stuff, just a few ideas thrown out here. *yelp*.


Comment on Re: •Re: It's a dog, but what kind? (polymorphism , in Perl OO)
Select or Download Code
Re: Re: •Re: It's a dog, but what kind? (polymorphism , in Perl OO)
by hardburn (Abbot) on Mar 23, 2004 at 21:17 UTC

    Polymorphism is a much more general concept, and we skip over that generality by starting with the factory piece first.

    See my reply below for why this isn't a good example of polymorphisim anyway. Update: blue_cowdawg's update fix the OP's polymorphisim issue.

    I would be interested to see if the factory could be made without using eval, as well...I think it can, especially if the dogs were loaded previously in a more-safe matter.

    It can using require $path_to_breed; instead of eval "use $breed;";. But it ammounts to almost the same thing, except that you have to specifiy the path to the breed file instead of the traditional 'module::name' format. As you say, it's also possible to load all the subclasses before anything is called, but that could get very inefficient fast.

    My favored solution would be to map a breed via a hash:

    my %breeds = ( cocker => 'dog::cocker', setter => 'dog::setter', ); sub new { my $class = shift; my $breed = shift; my $self = { }; if($breed) { my $breed_class = $breeds{$breed}; eval " use $breed_class "; die $@ if $@; $self = $breed_class->new(); } else { bless $self, $class; } return $self; }

    ----
    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

      As you say, it's also possible to load all the subclasses before anything is called, but that could get very inefficient fast.
      Understood. It could be a killer. As a non-perl example, Sun did something like this with java import in 1.4.x, and we saw numerous performance issues -- and we ended up reimplementing lazy loading of some plugins with reflection (i.e. equivalent of symbol tables) -- ugly!
      My favored solution would be to map a breed via a hash:
      Great idea, chief! I'd probably use both the hash and require for purity's sake -- and call the import explicitly. You might (I'm theorizing) save a little performance from not using eval at all in that case. But yeah, then you would lose the exception catching (eval block)???

        The only problem with require in this case is that if you use a variable for the module name, you have to specify the path to the module, not the bare name. Using eval STRING is the accepted idiom around this problem. Yes, it is slow, but it's probably minimal unless you're doing it in a tight loop. In this example, the error handling aspects of eval are a non-factor, since we're just dieing with the error message anyway. Of course, your own code may or may not do that.

        ----
        : () { :|:& };:

        Note: All code is untested, unless otherwise stated

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (3)
As of 2014-07-13 01:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    When choosing user names for websites, I prefer to use:








    Results (244 votes), past polls