Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

OOP - redefining a class

by nmerriweather (Friar)
on Jun 12, 2005 at 04:19 UTC ( [id://465900]=perlquestion: print w/replies, xml ) Need Help??

nmerriweather has asked for the wisdom of the Perl Monks concerning the following question:

In a large application I'm working on, a dispatch table creates a new object
$page = A:B:C->new();
Things have been getting kind of big lately, and I've realized I need more subclasses. Rather than doing this:
$page = A:B:C:D1->new(); $page = A:B:C:D2->new();
Perhaps I should rephrase: my code is making A:B:C when I should probably be making A:B:C:D1 -- but I want the init code in A:B:C to realize that i should be using a subclass instead of the parent class, and then automagically either morph into a subclass, access the subclass methods, or do something that achieves the result so that:
$page = A:B:C->new(); $page->check_if_i_should_be_a_subclass_instead(); $page->render(); # render method from A:B:C or A:B:C:D1 based on ab +ove method result

Replies are listed 'Best First'.
Re: OOP - redefining a class
by etcshadow (Priest) on Jun 12, 2005 at 05:25 UTC
    Yeah, it's not at all uncommon of a pattern. It also happens to be quite easily done in perl. Remember that an object is just a reference blessed into a package (or, more to the point, blessed into the name of a package).

    Something along these lines is a common approach:

    sub new { my ($class, @args) = @_; my $destination_class = figure_destination_class(@args); # or whate +ver my $self = bless {}, $destination_class; $self->initialize(@args); return $self; }
    One important note is that you'll want to move any actual initialization logic that might have been part of new out to another method (I called initialize), so that a subclass would have the ability to overload that logic, after the subclass is determined, and the object is blessed into that package.

    There are some potential gotchas, of course. Mostly to do with the questions of what the potential sub-classes are, and if/whether you automatically load their code on the fly. For example, you could extend the above to something along the lines of this:

    sub new { my ($class, @args) = @_; my $destination_class = figure_destination_class(@args); # or whate +ver # verify that the $destination_class is a valid package name # and a proper sub-namespace of $class, and detaint if ($destination_class =~ /^(\Q$class\E(?:::[a-zA-Z_]\w*)+)$/)) { eval "require $1" or die $@; } else { die "'$destination_class' is an invalid class name for sub-class +es of $class\n"; } my $self = bless {}, $destination_class; $self->initialize(@args); return $self; }
    Which does some checking of the package name before loading it (generally people refer to this act as "detainting", as it has the side effect of allowing a taint-check-enabled script to still do this ok... if you construct it properly).
    ------------ :Wq Not an editor command: Wq
Re: OOP - redefining a class
by spurperl (Priest) on Jun 12, 2005 at 04:27 UTC
    First of all, you probably mean :: and not : there as the class divider.

    As to your problem... I think you should read about some design patterns to get a general idea of where you are and where you want to get. "Factories", in particular.

Re: OOP - redefining a class
by adrianh (Chancellor) on Jun 12, 2005 at 21:06 UTC
    $page = A:B:C->new(); $page->check_if_i_should_be_a_subclass_instead(); $page->render(); # render method from A:B:C or A:B:C:D1 based on ab +ove method result

    This makes me think that what you might want is to separate out the rendering stuff into separate classes and then create your A::B::C object, passing in an appropriate rendering object.

    my $renderer = Renderer::D->new; my $page = A::B::C->new( renderer => $renderer );

Log In?
Username:
Password:

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

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

    No recent polls found