Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Reclassifying an object

by Amblikai (Scribe)
on Sep 29, 2015 at 10:53 UTC ( [id://1143331]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks!

I'm writing a script at the moment which takes a couple of data structures and builds some objects from them. The data structures are setup information for a database and data to be input into that database respectively

My question is do i make a decision on the data before choosing to bless each set of data as a particular class?

Or am i better off blessing the objects as a parent class regardless, and then deciding which "subclass" the objects belong to and reclassifying them?

Even if i choose the first route, i think i'm going to have to change the class of the data objects eventually. so what's the best way to go about it? I know i could just "bless" the object again with a different class but it feels a bit funky!

Any help appreciated as always!

Replies are listed 'Best First'.
Re: Reclassifying an object
by choroba (Cardinal) on Sep 29, 2015 at 11:05 UTC
    Using bare data structures makes it impossible to use methods. Therefore, using a parent class at the beginning sounds reasonable.

    The child classes could have a method to create an instance from a given parent class instance, and you can implement it any way you like - rebless the object, or rebless its clone, and so on, plus all the checks you need to allow the transition. Thus, the "dirty" code stays in the class and doesn't pollute your users' code.

    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      I follow you and thanks for your reply. I'm not sure how to go about reblessing the object though.

      As i see it i could:

      • Have the constructor call the method to determine the class, and immediately rebless the object as some other class. The problem i see here is that now the parent class has to have knowledge of it's child classes which i think breaks inheritance?
      • Or i could interrogate the type in the main script and create a clone of a different (sub)class. This seems inefficient to me and it seems like i'm bringing the code out of the classes and into the main script.

      Am i needlessly overcomplicating things?

      I found this code: Stack Overflow But to be honest i'm having real trouble following what the user is doing here!

        I imagined the second solution:
        my $obj = 'Parent'->new; $obj->populate(@data); for my $child_class (@possible_child_classes) { if (my $new = $child_class->new_from_parent($obj)) { $obj = $new; last } } # Don't forget to handle the case that $obj hasn't changed.

        In fact, the only problem why this shouldn't go to the parent class is the array of possible child classes. So, get it from outside; the parent can insist on its children implementing a method:

        sub new_from_parent { die "Should be overriden.\n" } sub rebless { my $self = shift; my @possible_child_classes = @_; for my $child_class (@possible_child_classes) { # etc. using $self instead of $obj.

        And the code becomes

        my $obj = 'Parent'->new; $obj->populate(@data); $obj->rebless(@possible_child_classes);
        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
        The problem i see here is that now the parent class has to have knowledge of it's child classes which i think breaks inheritance?

        As Salvor Hardin used to say, never let your sense of morals prevent you from doing what is right!

Re: Reclassifying an object
by Athanasius (Archbishop) on Sep 29, 2015 at 16:42 UTC

    Hello Amblikai,

    I would be interested to know why each data object’s class has to change. However, given that it does, I would prefer a design in which the client code knows only the parent class (i.e., the interface), and has no knowledge of the various child classes. (That is, child classes are treated as “implementation details.”) Here is a sketch of how this can be accomplished:

    The chief advantage of this design is that whenever a new Widget child class is added, the only existing code that needs to change is the rebless method in Widget.pm.1 Client code remains unaffected.

    1Update: Widget.pm must also use each of its child classes.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Reclassifying an object
by sundialsvc4 (Abbot) on Sep 29, 2015 at 17:15 UTC

    I have actually seen this done in a couple of other languages.   But, what was done was (basically ...) to initially instantiate an JustLoaded object, which possessed the necessary functionality to support loading things from a data source.   The programmers then provided a factory method, which would coin an instance of the proper thing and return it (or, raise an exception).   After that, the original object was discarded.

    In Perl, this idea can be simplified to “re-blessing.”   Instantiate an object that has support for the loading process, then re-bless it into its target class after confirming that all of the requisite instance-variables called for by that class do exist, and that the object is otherwise “sane.”   (Or, re-bless it, then call an internal-only method that performs that sanity-check.)

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (4)
As of 2024-04-16 05:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found