Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

My first attempt at inheritance

by BillKSmith (Chaplain)
on May 31, 2013 at 18:40 UTC ( #1036290=perlquestion: print w/ replies, xml ) Need Help??
BillKSmith has asked for the wisdom of the Perl Monks concerning the following question:

I want to derive a new class from IO::Dir. The only difference should be that the new class overrides the read method with a new one which only returns .pl files. To keep things as simple as possible, Version 0 of the new method does nothing but return undef. The following code always returns the message:

Can't find method "new" via package "IO::Dir::pl"...

use strict; use warnings; use Autodie; use IO::Dir; my $dh = IO::Dir::pl->new('.'); while (my $file_name = $dh->read_pl()){ print STDOUT "$file_name\n"; } package IO::Dir::pl; use vars '@ISA'; @ISA = ('IO::Dir'); sub read{ my $self = shift; warn "Ok We got here.\n"; return undef; }

The @ISA array does not appear to work as expected.

Bill

Comment on My first attempt at inheritance
Download Code
Re: My first attempt at inheritance
by shmem (Canon) on May 31, 2013 at 19:02 UTC
    The @ISA array does not appear to work as expected.

    True. I guess that's because at runtime IO::Dir::pl->new is called before its namespace is set up proper and its @ISA populated. Wrapping that namespace definition into a BEGIN block fixes that.
    And you call the method read_pl(), but all you have is read() in IO::Dir::pl.

    use strict; use warnings; use autodie; # not Autodie (update) use IO::Dir; my $dh = IO::Dir::pl->new('.'); while (my $file_name = $dh->read_pl()){ print STDOUT "$file_name\n"; } BEGIN { package IO::Dir::pl; use vars '@ISA'; @ISA = ('IO::Dir'); sub read_pl { my $self = shift; warn "Ok We got here.\n"; return undef; } }
      Just moving the package definition higher in the file helps. Also, Autodie should probably be autodie.
      لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

        Of course it does. But maybe throwing in BEGIN and a pair of curlies has a good side effect on the OP.

Re: My first attempt at inheritance
by tobyink (Abbot) on May 31, 2013 at 20:47 UTC

    You might be interested in Subclass::Of, an idea I've been working on recently...

    #!/usr/bin/env perl use strict; use warnings; use Subclass::Of "IO::Dir", -as => "My_IO_Dir", -methods => [ read_pl => sub { my $self = shift; warn "Ok We got here.\n"; return undef; }, ]; my $dh = My_IO_Dir->new('.'); while (my $file_name = $dh->read_pl()) { print STDOUT "$file_name\n"; }
    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: My first attempt at inheritance
by perl-diddler (Hermit) on Jun 01, 2013 at 02:34 UTC
    If you are going to use IO::Dir::pl->new you need to have defined IO::Dir::pl before you used it.

    I.e. you can't just take a random class name and use it as an object or perl will complain:

    perl -we'use strict; my $foo=Data::Vars->new();' Can't locate object method "new" via package "Data::Vars" (perhaps you + forgot to load "Data::Vars"?) at -e line 1. > grep 'sub.*new' lib/Data/Vars.pm sub new (;$) { # return blessed objects and init pre-define +d fields w/args
    you have to "use" (or have it defined first) a class (so perl can know where to attach things) BEFORE you use it.

    That's the 1st problem.

    Second problem is -- what are you trying to do?

    Your first routine calls IO::DIR::pl->new, but I don't see any 'new' in IO::dir::pl.

    You *can't rely* on inheritance yet, as you don't have a Blessed Object!

    Third problem is you call "read_pl", in your class, but have no read_pl. (did you mean read?) So if you fix those, things, it works, but not well:

    #!/usr/bin/perl -w use strict; use warnings; use IO::Dir; my $dh=bless {}, 'IO::Dir::pl'; #my $dh = IO::Dir::pl->new('.'); while (my $file_name = $dh->read()){ print STDOUT "$file_name\n"; exit; } { package IO::Dir::pl; use strict; use warnings; our @ISA; @ISA = qw(IO::Dir); sub read{ my $self = shift; warn "Ok We got here.\n"; return undef; } } > /tmp/p Ok We got here. (in cleanup) Not a GLOB reference at /usr/lib/perl5/5.16.2/x86 +_64-linux-thread-multi/IO/Dir.pm line 43.
    If you Just switch around things so your definition occurs before you use it:
    #!/usr/bin/perl -w { package IO::Dir::pl; use strict; use warnings; our @ISA; @ISA = qw(IO::Dir); sub read{ my $self = shift; warn "Ok We got here.\n"; return undef; } } use strict; use warnings; use IO::Dir; my $dh = IO::Dir::pl->new('.'); while (my $file_name = $dh->read()){ print STDOUT "$file_name\n"; exit; } > /tmp/p Ok We got here.
    That does what you want...

    (I think?)

      "Your first routine calls IO::DIR::pl->new, but I don't see any 'new' in IO::dir::pl.

      "You *can't rely* on inheritance yet, as you don't have a Blessed Object!"

      Not true. Inheritance works on class methods too. Look ma, no blessed objects!

      use v5.12; use strict; use warnings; require File::Spec; @File::Spectacles::ISA = "File::Spec"; say File::Spectacles->tmpdir;

      The OP's entire problem was that he was trying to rely on IO::Dir::pl's inheritance, before he'd assigned anything to @ISA.

      Adding @IO::Dir::pl::ISA = "IO::Dir" to the beginning of the file suffices to fix it. (Though it's probably not the solution I'd use personally.)

      Update: sorry - fixed code.

      package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
        Um...did you try that...doesn't work here...
        > perl -e ' use v5.12; use strict; use warnings; @File::Spectacles::ISA = "File::Spec"; say File::Spectacles->tmpdir;' Can't locate package File::Spec for @File::Spectacles::ISA at -e line +7. Can't locate package File::Spec for @File::Spectacles::ISA at -e line +7. Can't locate object method "tmpdir" via package "File::Spectacles" at +-e line 7.
        Vs. if you put the use in:
        > perl -e ' use File::Spec; use v5.12; use strict; use warnings; @File::Spectacles::ISA = "File::Spec"; say File::Spectacles->tmpdir;' /tmp
        I've always had to put in a 'use' before it would work... But your perl may be different (works without pre-declaring things.)...hmmm.... I'm using 5.16.2...BTW...maybe this is something that changed, though I seem to remember it being around for a while...?? But then I remember the easter bunny just like it was yes...er...scratch that.

        Um... So did you actually try your example? -- didn't work here. Sorry... :-(

Re: My first attempt at inheritance
by Anonymous Monk on Jun 01, 2013 at 14:06 UTC
    You only need to make 2 minor adjustments.
    First, change $dh->read_pl() to $dh->read

    Then fix the @ISA assignment by using parent.

    #!/usr/bin/perl use strict; use warnings; use autodie; use IO::Dir; my $dh = IO::Dir::pl->new('.'); while (my $file_name = $dh->read){ print STDOUT "$file_name\n"; } package IO::Dir::pl; use parent -norequire, qw(IO::Dir); sub read{ my $self = shift; warn "Ok We got here.\n"; return undef; }

      I probably should have logged-in before posting that comment.

      Hello Bill, I see we both get around the different forums.

      FishMonger
      aka Ron Bergin

        Thanks to all! After reading up on all your suggestions, I plan on using the first (BEGIN). The error in my method name was left over from a failed attempt to find my problem myself.

        Ron, I'm afraid that you will always be "the fishmonger".

        Bill

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1036290]
Approved by shmem
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (10)
As of 2014-07-13 17:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    When choosing user names for websites, I prefer to use:








    Results (251 votes), past polls