lightbringer has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I'm trying to implement overriding methods. This is my code:

Base class:

use Net::Telnet(); use strict; use warnings; package L_Switch; sub new { my $class = shift; my ($location, $ip, $time, $client) = @_; my $self = {}; my $sucClass; if ((defined $client) and ($client eq "Veda")){ $subClass = "L_Switch::L_Veda"; } eval "use $subClass;"; eval "\$self = $subClass -> new();"; } sub login { my $self = shift; my $utility = L_Utility -> new(); $self -> {'telnetConn'} -> open($self -> {ip}); $self -> {'telnetConn'} -> login($self -> {'username'}, $self -> { +'password'}); if ($self -> {'time_out'} == 1) # checking +timed-out switches { $self -> {'full_info'} = $self -> {'full_info'} . "," . $self +-> {'location'}; $self -> {'full_info'} = $self -> {'full_info'} . "," . $self +-> {'fault'} . "," . $self -> {'time'} . ",,,,,"; return $self -> {'full_info'}; } return "0"; } 1;

Child class:

package L_Switch::L_Veda; require L_Switch; @ISA = qw(L_Switch); use strict; use warnings; use NET::SSH2; sub new { } # something in here sub login { my $self = shift; $self -> {'ssh'} -> connect($self -> {'ip'}); $self -> {'ssh'} -> auth_password($self -> {'username'}, $self -> +{'password'}); return 0; } 1;

Main script:

use L_Switch; use strict; use warnings; my $utility = L_Utility -> new(); my $switch = L_Switch -> new("", '127.0.0.1', "", "Veda"); $switch -> login(); print $switch -> getFullInfo();
when I run the script, an error appeared: Can't locate object method "login" via package "L_Switch::L_Veda" at testSSH.pl line xx. Can anyone tell me what went wrong in my code. Thanks in advance

Replies are listed 'Best First'.
Re: Perl does not recognize object method
by ig (Vicar) on Jul 06, 2012 at 09:57 UTC

    I don't see an obvious cause of the error you get in the code you posted, but what you posted is obviously not what you ran when you got the error, so that doesn't mean much.

    Maybe the following code does something like what you want and you can incorporate how it does it into your code.

    use strict; use warnings; use Data::Dumper; package ClassA; sub new { my $class = shift; my ($client) = @_; my $self = bless {}, $class; if($client eq 'Veda') { $self = ClassB->new(); } return $self; } sub login { print "ClassA login\n"; } package ClassB; sub new { my $class = shift; bless {}, $class; } sub login { print "ClassB login\n"; } package main; print "obj1\n"; my $obj1 = ClassA->new('Veda'); print Dumper($obj1); $obj1->login(); print "obj2\n"; my $obj2 = ClassA->new('Other'); print Dumper($obj2); $obj2->login();

    Output is

    obj1 $VAR1 = bless( {}, 'ClassB' ); ClassB login obj2 $VAR1 = bless( {}, 'ClassA' ); ClassA login
Re: Perl does not recognize object method
by zentara (Cardinal) on Jul 06, 2012 at 09:58 UTC
Re: Perl does not recognize object method
by frozenwithjoy (Priest) on Jul 06, 2012 at 07:34 UTC
    I tried to run these to help with troubleshooting, but L_Utility wasn't included in your code. It is probably unrelated, but I did notice a typo on line 10 of L_Switch.pm. I believe my $sucClass; should be my $subClass;.
Re: Perl does not recognize object method
by Athanasius (Archbishop) on Jul 07, 2012 at 02:52 UTC

    Just a comment from the viewpoint of OOD:

    The $switch object is currently created via:

    my $switch = L_Switch -> new("", '127.0.0.1', "", "Veda");

    which explicitly mentions "Veda" anyway. If this is instead rewritten as:

    my $switch = L_Switch::L_Veda -> new("", '127.0.0.1', "");

    there will be no need for a factory method constructor in the base class, and the implementation of L_Switch::new can be greatly simplified.

    As a general rule, wherever possible a base class should know nothing about its subclasses. This makes for a simpler and much cleaner OO design.

    Athanasius <°(((><contra mundum