I'm trying to get 'super' to work in a prototype-based OO system and currently have this ugly mess. I'm wondering if there is a better way.

The system uses hash-based objects which can have CODE ref entries which are run to provide per-object behaviour. It has single inheritence so 'super' is not too complicated. I hope the intent is clear without all the entire class.

The ideal solution would have 'super' know which code ref called it and then find the next in the object_can_all list. Next best would be a syntactic improvement to make the second form below easier. Ideas? Suggestions?

=item super Call the prototype's/parent's version of a function. This is tricky because the when coding the $self->super call intends to target one thing but a subclass of this will provide a different $self that has the original as it's prototype. So super needs to discover when this has happened, seemingly impossible using just caller($n) and $self. More information is needed from 'new' time. That's why there's two interface variants: $self->super(check => @_); This asserts that there are only two "check" routines in the prototype chain for $self and it calls the last one (which assumes that only the first/sub-object uses super). The second variant requires a more complex declaration, permitting more than two subs in a hierarchy. You must pass super a coderef to the surrounding code so that it can find it in the list of potential versions. use WeakRef; my $this_sub; $this_sub = sub { my $self = shift; $self->super($this_sub, check => @_); } $object->{check} = $this_sub; weaken $this_sub; The weaken is important to avoid a circular reference as the closure captures $start_code_ref. This interface division means that objects must use the second form if they want to their sub-objects to be able to override a method using super. Requiring adjustments to the parent is ugly but seems to be the only solution. Devel::Caller provides caller_cx which would help but it is seems flak +y. =cut sub super { if(ref $_[1] ne 'CODE') { # No code ref, super must be unambiguous my ($self, $attr) = (shift, shift); # Find all versions of $attr for this object my @subs = $self->object_can_all($attr); die "Ambiguous super call for $attr on $self" if @subs != 2; # Super must be intended for the second (ie. last) one my $super_sub = pop @subs; return $self->$super_sub(@_); } else { # They gave us a reference to the intended start sub my ($self, $this_sub, $attr) = (shift, shift, shift); # Find where $this_sub is my @subs = $self->object_can_all($attr); my $n = 0; while ($subs[$n] != $this_sub) { $n++ } # Run the next highest one die "No super for $attr on $self" unless exists $subs[$n+1]; my $super_sub = $subs[$n+1]; return $self->$super_sub(@_); } }

In reply to Sub getting it's own CODE ref? Proto-OO by bsb

Title:
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, details, 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, summary, 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.