Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"

comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

The background

This meditation directly follows the discussion around the OOP tutorial, especially the thread after this node.

I must admit i hadn't thought of a solution to that problem successfully before, although i've had this problem whenever i really wanted to subclass a module i didn't write. It wasn't possible, because whatever new attribute i introduced, i could not be sure it wouldn't break something with the next version of the Superclass...

Abigail-II's solution does not only seem to solve that, it does solve the problem. As pointed out in posts in the above mentioned discussion, this technique makes it neccessary to use accessor/mutator methods, which is what we want when we use OO.

So I've come to the conclusion that these "Inside Out" objects (as Abigail calls them) are the better approach when you want subclassable OO. There's no need to rewrite classes that use the popular way, most classes aren't subclassed anyway, but if you wanted to subclass GD::Image you'd have a problem: how to call your member variables?

The next step

There are some weaknesses that might seriously stop you from thinking the solution is useful. But wait: They're there because it's not the popular way.

My contribution is an RFC: A superclass for all classes using that new methodology to solve at least four of these problems: the DESTROY method, the lexically limited data-variables, the serialization issue and finally the methodmaker. Probably the stringification problem can be solved generally in that class.

I have already posted an idea in the disucussion, but this already has developed and here comes the result:

package OO; use strict; use warnings; use Carp qw/croak/;

This is the first question: the name, how should that superclass be called? 'OO' is just a thought and probably no too good idea.

#-------------------------------------------------------------------- # The registry itself: storing all the data of your objects #-------------------------------------------------------------------- my %Object = (); # Object => Class => Attribute

This is not a question, but the idea: Store all the information right here in that lexical. A question is the structure: Class,Field,Object, which would more directly inherit Abigail's idea or Object,Class,Field, which has the advantage that the destruction can be done easily without tricks or search.

#-------------------------------------------------------------------- # inheritable constructor with generalized behaviour #-------------------------------------------------------------------- sub new { my $class = shift; my $self = bless [caller], $class; # is that neccessary if you can override new()? if( $self->can( 'initialize' ) ){ $self->initialize( @_ ); } return $self; }

Should there be something like this constructor at all? You see, it is quite unneccessary, but what else should a constructor do and why should every class write something similar?

#-------------------------------------------------------------------- # Use these two methods to get and set members of your # object and they will do encapsulation for you # # BE CONSISTENT our your OO will BREAK! # #-------------------------------------------------------------------- sub oo_get { my $obj = shift; my $field = shift; # member hash is based on caller class # and may be overwritten by third argument to get() my $class = @_ ? shift : caller; $Object{ $obj }{ $class }{ $field } } sub oo_set { my $obj = shift; my $field = shift; my $value = shift; my $class = @_ ? shift : caller; $Object{ $obj }{ $class }{ $field } = $value; }

These two are the crucial point of the whole thing: They get/store attribute data depending on the caller. What? Yes. These two are not to be used anywhere except in the package that defines a class. This way each class has it's own data slot as the idea is.

The names of these two must be carefully chosen, but probably 'oo_' can be avoided by classes easily.

#-------------------------------------------------------------------- # most important: DESTROY #-------------------------------------------------------------------- sub DESTROY { my $obj = shift; delete $Object{ $obj } #that's why the structure of the regist +ry was chosen like that }

Jep, that's all about the possible memory leaks. Object deletion causes object data deletion. by having this in the superclass, you needn't rewrite it in every class.

#-------------------------------------------------------------------- # create_accessor class method to create simple accessor/mutator + methods #-------------------------------------------------------------------- sub oo_create_accessor { my $pkg = shift; no strict 'refs'; # we're messing around with the symbol table foreach my $mem ( @_ ){ my $symbol = $pkg . '::' . $mem; if( defined *{ $symbol } ){ croak "Attempt to redefine $symbol via create_ +accessor"; } else { *{ $symbol } = sub { my $self = shift; if( @_ ){ $self->oo_set( $mem , $_[0] , +$pkg ); } else { $self->oo_get( $mem , $pkg ); } }; } } }

This is clear and is subject to be made more advanced but shows that it's easy to create accessor/mutator methods ala MethodMaker.

#-------------------------------------------------------------------- # debugging function/method (as you like it) #-------------------------------------------------------------------- sub oo_registry { return \%Object } 1;

further steps

Now one can write a serialization/deserialization method in that class. The stringification thing can be helped out using overload::StrVal as proposed by adrianh.

I hope this RFC is an inspiration to some as Abigail's post was inspiration to me.


In reply to A different OO approach by fruiture

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others contemplating the Monastery: (2)
    As of 2021-05-10 00:46 GMT
    Find Nodes?
      Voting Booth?
      Perl 7 will be out ...

      Results (103 votes). Check out past polls.