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

Hi, i have made a set of perl modules and CGIs for creating online exercises (multiple choice, etc). It's called OEME and its hosted on CodigoLivre (http://www.codigolivre.org.br/projects/oeme), if you fell like taking a look at it. Well, the thing is, I created a superclass Question, and subclasses to it to actually be each kind of question. Question has the normal acessor functions, that are used in all Question::* classes.

Each question is set on a PostgreSQL database, each type on a differente table. Each id can be gotten with the following SQL command SELECT NEXTVAL('tablename_id'). That works for all subclasses. So I defined a constant in each subclass, called table, that contains the name of the table, and a _get_new_id function in the Question superclass, that does the select according to the table name of $self, wich will, off course, call the table function(constant) of the subclass.

Now, everything I ever read about OO (even in the moral liberal perl world) says one should never let superclass acess subclass data. So I ask, is this technique I describe actually superclass acessing subclass data? And if so, is it justifiable to do it? And is there another, more correct in the OO sense, way to do it?

Thanks in advance,
Paulo Schreiner

Edit by tye

Replies are listed 'Best First'.
Re: Superclass acessing sublass data
by adrianh (Chancellor) on Dec 19, 2002 at 13:20 UTC
    is this technique I describe actually superclass acessing subclass data

    No.

    Superclass objects cannot get to the constant - only objects in the sub-class in question.

    What you are defining is an abstract interface - every Question class should have a get_table_name method (or whatever your constant is called).

    Each sub-class is then giving its own concrete implementation to get_table_name (or whatever).

    It's a commonly accepted technique.

    Take a look at Refactoring: Soft-code class name in factory method and Re: Re: Extending object you don't create which do similar things with class names rather than table names.

Re: Superclass acessing sublass data
by djantzen (Priest) on Dec 19, 2002 at 17:32 UTC

    No, adrianh is absolutely correct. In fact, this is very good style because it allows inheritance of behavior while allowing alterations to that behavior transparently based upon the concrete subclass you are actually instantiating.

    Here's an example of bad, inflexible, child-snooping that you want to be concerned about:

    package FamilyMember; # the parent class of Son, Daughter sub new { my ($class, $args) = @_; my $self = bless({}, $class); if ($class eq 'Son') { $self->askSantaFor('A Truck!'); } elsif ($class eq Daughter') { $self->askSantaFor("Subscription to Martha Stewart's 'Living'" +); } return $self; } sub askSantaFor { my ($self, $wish); push @{$self->{things_to_ask_for}}, $wish; }

    What happens if you need to add a new subclass called StepDaughter? You have to go to the superclass and modify the constructor. The better way is just what you've done, and in this silly example the solution would be either to override askSantaFor in each subclass, or (even better) provide a class specific method, perhaps called wishList, that provides the appropriate parameters to the method called from the superclass constructor. Thus the above example code could be changed to:

    sub new { my ($class, $args) = @_; my $self = bless({}, $class); $self->askSantaFor($class->wishList()); return $self; }

    Hope that helps, DJ