I think you have your question backwards. You really want to call superclass methods.

You're conflating two OO idioms - inheritance (what you're derived from - in perl, we set @ISA, but better is base, and better yet is parent, and, depending on who you ask, there are better options available in Moose, Moo, and others), and composition (also known as "Has-A" - as in, FFMech Has A WWW::Mechanize::Firefox object). Don't do both for the same type.

You need to pick one. In general, if you want to expose nearly everything, maybe with a few tweaks, inheritance is easier. To set that up, you just use parent 'WWW::Mechanize::Firefox'; and you're mostly done. In your case, I see you have some extra defaults, so you can pass them on in your overridden new:

sub new { my ($class, %args) = @_; my $self = $class->SUPER::new(launch => 'firefox', activate => 1, %a +rgs); $self->{_window_id} = FindWindowLike('Mozilla Firefox); ClickWindow($self->{_window_id}); if ($self->title =~ /Restore Session/i) { $self->click( { selector => '#errorCancel' } ); } return $self; }
And you call this as my $ffm = FFMech->new(...);. I leave it as an exercise for the reader to extend this out to the EventRepository subclass - it's far simpler.

You'll notice that this no longer needs to call $self->{_mech} for getting to the mech object - because $self @ISA mech object, fully initialised!

For composition, you don't want to set up the @ISA relationship, so you don't set @ISA, call use parent or base or anything like that. Just use WWW::Mechanize::Firefox; to ensure it's loaded, and then you can create it in your constructor. However, then you have to redirect the interfaces you want to expose, e.g.:

sub get { my $self = shift; $self->{_mech}->get(@_); }
This can get annoying, so you could generate these functions:
for my $func (qw(get click ...)) { no strict 'refs'; *$func = sub { my $self = shift; $self->{_mech}->$func(@_); }; }
You can reduce the scope of that no strict 'refs' bit even more, I'm just being lazy and not testing stuff here, because there's a better way. You remember how I mentioned that there are better options than parent? Moose (and maybe Moo - I haven't used Moo) allows you to say you have a member variable which "handles" certain methods, and Moose will generate the redirection methods for you:
use Moose; has _mech => ( is => 'rw', handles => [ qw(get click ...) ] );
Mind you, this will take a bit more work to set up so that you could make that _mech readonly ('ro') and such, and this becomes a dark, deep rabbit hole you can chase forever :) but it will forever transform the way you do OO in perl. Personally, a project has to cross a fuzzy threshold to warrant using Moose, but when it does, then I use it. The downside to this heuristic is that if a project starts out small and then scope creep happens, it can cross that threshold and switching to Moose becomes a bit extra work than if I know it'll be big from the outset and reach for Moose from the beginning.


In reply to Re: Proper way to call subclass methods? by Tanktalus
in thread Proper way to call subclass methods? by nysus

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