Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
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 avoiding work at the Monastery: (10)
As of 2014-09-19 15:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (142 votes), past polls