Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Inheritance without defining the object on inherited module

by thanos1983 (Parson)
on May 18, 2015 at 08:28 UTC ( [id://1126955]=perlquestion: print w/replies, xml ) Need Help??

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

Dear Monks,

I am new to the OO programming in general and also in Perl. I found this tutorials Object Oriented Programming in PERL that I am following and trying to understand how to use Inheritance.

I have a created a similar code example from the tutorial, but I can not figure out how to call a method from another module without having to define the object inside the module.

Sample of code to replicate my problem:

mainl.pl

#!/usr/bin/perl use Employee; use strict; use warnings; my $object = new Person( "Thanos", "Test", 123456); # Get first name which is set using constructor. my $firstName = $object->getFirstName(); print "Before Setting First Name is : $firstName\n"; # Now Set first name using helper function. $object->setFirstName( "Than." ); # Now get first name set by helper function. $firstName = $object->getFirstName(); print "Before Setting First Name is : $firstName\n";

Person.pm

#!/usr/bin/perl use strict; use warnings; package Person; sub new { my $class = shift; my $self = { _firstName => shift, _lastName => shift, _ssn => shift, }; # Print all the values just for clarification. print "First Name is $self->{_firstName}\n"; print "Last Name is $self->{_lastName}\n"; print "SSN is $self->{_ssn}\n"; bless $self, $class; return $self; } sub setFirstName { my ( $self, $firstName ) = @_; $self->{_firstName} = $firstName if defined($firstName); return $self->{_firstName}; } sub getFirstName { my( $self ) = @_; return $self->{_firstName}; } 1;

Employee.pm

#!/usr/bin/perl use strict; use warnings; package Employee; use Person; our @ISA = qw(Person); # inherits from Person my $firstName = $object->getFirstName(); print "This is the first name: " . $firstName . "\n"; 1; =comment How can I use the method my $firstName = $object->getFirstName(); without creating the object? =cut

The error that I am getting when I execute the code:

Global symbol "$object" requires explicit package name at Employee.pm +line 10. Compilation failed in require at main.pl line 2. BEGIN failed--compilation aborted at main.pl line 2.

How can I call the method, without the need to define the object again! I assume there is a way since I am using inheritance.

Thanks in advance for time and effort trying to answer my simple question.

Seeking for Perl wisdom...on the process of learning...not there...yet!

Replies are listed 'Best First'.
Re: Inheritance without defining the object on inherited module
by Corion (Patriarch) on May 18, 2015 at 09:16 UTC
    ... our @ISA = qw(Person); # inherits from Person my $firstName = $object->getFirstName(); print "This is the first name: " . $firstName . "\n";

    Can you explain in English what this code is supposed to do and when it is supposed to be executed?

    The code is not in a subroutine so it will run at use time.

      Hello Corion,

      This is actually the key point of my question. I want to find a way to pass/ inherit the value to my $firstName when the module will be called.

      My intention is to use warnings on my script instead of die functions and store the error on a directory.

      Sample of pseudo code Employee.pm:

      So my question is how to pass the $fileDirectory into %WARNS so I can use it to print the error on correct location. I can pass it as a parameter through main.pl.

      Sample of new main.pl:

      #!/usr/bin/perl use Person; use strict; use warnings; use Employee; my $dirToBePassed = "/path/Dir"; my $object = new Person( "Thanos", "Test", 123456); my $firstName = $object->getFirstName(); print "This is the first name: $firstName\n"; my $secondObject = new Employee( "refToBeUsed" ); my $solution = $secondObject->somethingCalledFromMain(); print "This is the solution : $solution\n";

      Sample of new Employee.pm

      #!/usr/bin/perl use strict; use warnings; package Employee; sub new { my $class = shift; my $self = { refFromMain => shift, }; bless $self, $class; return $self; } sub somethingCalledFromMain { my( $self ) = @_; =comment do something here; warn "I was not able to complete the process!\n"; =cut return $self->{refFromMain}; } my %WARNS; local $SIG{__WARN__} = sub { my $message = shift; return if $WARNS{$message}++; logger('warning', $message); }; sub logger { my ($level, $msg) = @_; if (open my $out, '>>', 'log.txt') { chomp $msg; print $out "$level - $msg\n"; close $out; } } 1;

      Sample of working output:

      This is the first name: Thanos This is the solution : refToBeUsed

      It is really easy to pass the my $dirToBePassed = "/path/Dir"; to Employee.pm as somethingCalledFromMain($dirToBePassed); with minor code modifications. The problem is how to pass this parameter to %WARNS. So I can print the warnings on the correct directory.

      Thank you for your time and effort reading and replying to my question.

      Seeking for Perl wisdom...on the process of learning...not there...yet!

        Your problem does not show anything related to inheritance - the code shows no relation between Person and Employee.

        If you want to do a global capturing of all warnings raised by code in the Employee class, you will need to store the "current" Employee instance in a global variable and then reuse that variable in your %SIG handler for warnings. The easiest approach is to set the "current" employee in the main program:

        local $Employee::current= $secondObject; $secondObject->doSomethingThatRaisesWarnings();

        Note that your statement of

        local $SIG{__WARN__} = sub { ... }

        loses its effect as soon as Employee.pm has been compiled. This may or may not be what you want.

        Personally, I would recommend to avoid capturing warnings in such a global way. I think it's better to have your Employee (or Person) class implement a ->logMessage() or ->warn() method that will store the warning with the employee.

        Its simple :P use Log::Log4perl / Log::Log4perl::FAQ

        Does this make sense ?

        Employee::logger_outfile( "/path/Dir" ); ... ##Employee.pm my $outfile ; sub Employee::logger_outfile { my $path = shift; croak "This is not a method" if ref $path or int@_; $outfile = $path; } sub Employee::logger { open ... $outfile ... }
Re: Inheritance without defining the object on inherited module
by QM (Parson) on May 18, 2015 at 08:39 UTC
    The quick and dirty answer is that in Employee.pm, $object is not defined. Which is because in main.pl you call new Person ... instead of new Employee.

    But there are no methods in Employee.pm: all of that codes runs at use time, called from main.pl.

    For purposes of demonstration, you probably want to wrap the print in Employee.pm as a printme method, and call it from main, such as $object->printme().

    Update:

    Don't forget to change $object to the $self idiom.

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of

      Hello QM

      I read again and again your answer but it is not so clear to me. Is it possible to provide a short sample code of the solution that you propose.

      Thanks in advance.

      Seeking for Perl wisdom...on the process of learning...not there...yet!
Re: Inheritance without defining the object on inherited module
by jeffa (Bishop) on May 18, 2015 at 17:49 UTC

    Yes, that error is occurring because you did not declare a variable. But there is a bigger issue: you are trying to execute some code that should be in your client inside your object. Do this instead:

    Moose and alternatives can simplify the learning curve:

    package Person; use Moose; use MooseX::FollowPBP; has firstName => ( is => 'rw', isa => 'Str', required => 1 ); has lastName => ( is => 'rw', isa => 'Str', required => 1 ); has ssn => ( is => 'ro', isa => 'Str' ); sub get_Name { join ' ', $_[0]->get_firstName, $_[0]->get_lastName } package Employee; use Moose; extends 'Person'; package main; use strict; use warnings; my @objects = ( Person->new( firstName => "Thanos", lastName => "Test", ssn => 123 +456), Employee->new( firstName => "Janus", lastName => "Employee", ssn = +> 998877), ); print $_->get_Name, $/ for @objects;

    Finally, i can't vouch for that tutorial you linked to. Try perlbootut instead?

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: Inheritance without defining the object on inherited module
by Anonymous Monk on May 18, 2015 at 08:43 UTC

    ... http://www.tutorialspoint.com/perl/perl_oo_perl.htm ...

    I suggest you start over, while the articles don't include publish date, its very old tutorial, it includes diy hand rolled CGI parameter parsing ... bad practice since 1993

    Start with Modern Perl a loose description of how experienced and effective Perl 5 programmers work....You can learn this too.

    Or perloop

    The error that I am getting when I execute the code: Global symbol "$object" requires explicit package name at Employee.pm

    I suggest you forget about OOP until you learn about variables and subroutines

    Coping with Scoping and Modern Perl give a good introduction

    For more quality up to date tutorials see Perl Tutorial Hub

      Hello Anonymous Monk,

      I assumed that this is an old tutorial, it looks like it but for a beginner on OO programming it was like a good start.

      I have some experience on the areas that you mentioned but I am having difficulty to understand how to overcome my problem.

      Thanks again for your time and effort, reading and replying to my question.

      Seeking for Perl wisdom...on the process of learning...not there...yet!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1126955]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (7)
As of 2024-03-28 11:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found