Showing posts with label perl. Show all posts
Showing posts with label perl. Show all posts

Thursday, 10 February 2011

Perl: how to inherit and modify the constructor of parent class

This reminder post will be by example, but basically talks about how to inherit a constructor from a parent class, then modify it slightly.  It's also a good case for remembering the reason for this blog - which is to serve as assistance to my memory, and isn't in any way a guidebook or even set of suggestions for how to do things.  This is particularly true of my forays into perl hackery.

Right then.  For this example, we'll start with two simple classes, "Parent" and "Child".  The inheritance relationship works exactly as you'd expect from the names:


Code for inheritance1.pl

#!/usr/bin/perl -w

use strict;

#--------------------------------

package Parent;
sub new {
    my $class=shift;
    my $string1=shift;
    print("1) Called $class constructor with: " . $string1 . "\n");
    my $self={
        string1 => $string1,
        };
    bless($self, $class);
    return $self;
    }

1;

#--------------------------------

package Child;
our @ISA='Parent';
sub new {
    my $class=shift;
    my $string1=shift;
    my $self=Parent->new($string1);
    print("2) Called $class constructor with: " . $string1 . "\n");
    bless($self,$class);
    return $self;
    }

1;

#--------------------------------


my $testObject1=Parent->new("Parent's String");
my $testObject2=Child->new("Child's String");

print("Parent object has stored: ",$testObject1->{string1},"\n");
print("Child object has stored: ",$testObject2->{string1},"\n");

exit 0;


This produces the output:
1) Called Parent constructor with: Parent's String
1) Called Parent constructor with: Child's String
2) Called Child constructor with: Child's String
Parent object has stored: Parent's String
Child object has stored: Child's String




The line of interest here is:
    my $self=Parent->new($string1);

Here the constructor for Child inherits the properties of the constructor for Parent.  As a result, whenever we call the constructor for Child, we see that code from the parent constructor is run.  Additional code from the Child constructor is also run.  However we've really done nothing useful here, as we haven't added any great extra feature to the Child constructor.  So what if we want to store a new parameter into our new object?



Code for inheritance2.pl

#!/usr/bin/perl -w

use strict;

#--------------------------------

package Parent;
sub new {
    my $class=shift;
    my $string1=shift;
    print("1) Called $class constructor with: " . $string1 . "\n");
    my $self={
        string1 => $string1,
        };
    bless($self, $class);
    return $self;
    }

1;

#--------------------------------

package Child;
our @ISA='Parent';
sub new {
    my $class=shift;
    my $string1=shift;
    my $string2=shift;
    my $self=Parent->new($string1);
    print("2) Called $class constructor with: " . $string2 . "\n");
    $self={
        string2 => $string2,
        };
    bless($self,$class);
    return $self;
    }

1;

#--------------------------------


my $testObject1=Parent->new("Parent's String");
my $testObject2=Child->new("Child's 1st String","Child's 2nd String");

print("Parent object has stored: ",$testObject1->{string1},"\n");
print("Child object has stored: ",$testObject2->{string1},"\n");
print("Child object has stored: ",$testObject2->{string2},"\n");

exit 0;


This produces the output:
1) Called Parent constructor with: Parent's String
1) Called Parent constructor with: Child's 1st String
2) Called Child constructor with: Child's 2nd String
Parent object has stored: Parent's String
Use of uninitialized value in print at ./inheritance2.pl line 47.
Child object has stored:
Child object has stored: Child's 2nd String



That didn't work at all!  That shouldn't be too much of a surprise, really, as we've overwritten the declaration of the $self hash.  We could expand it to include everything that the Parent class has, and in this case, it wouldn't take a lot of extra typing, but it's hardly making use of our Object Oriented design, and if there was lots of exciting configuration defined by the $self declaration, we'd lose it all, or have to recreate it.  Better is:



Code for inheritance3.pl
#!/usr/bin/perl -w

use strict;

#--------------------------------

package Parent;
sub new {
    my $class=shift;
    my $string1=shift;
    print("1) Called $class constructor with: " . $string1 . "\n");
    my $self={
        string1 => $string1,
        };
    bless($self, $class);
    return $self;
    }

1;

#--------------------------------

package Child;
our @ISA='Parent';
sub new {
    my $class=shift;
    my $string1=shift;
    my $string2=shift;
    my $self=Parent->new($string1);
    $self->{string2} = $string2;
    print("2) Called $class constructor with: " . $string2 . "\n");
    bless($self,$class);
    return $self;
    }

1;

#--------------------------------


my $testObject1=Parent->new("Parent's String");
my $testObject2=Child->new("Child's 1st String","Child's 2nd String");

print("Parent object has stored: ",$testObject1->{string1},"\n");
print("Child object has stored: ",$testObject2->{string1},"\n");
print("Child object has stored: ",$testObject2->{string2},"\n");

exit 0;


This produces the output:
1) Called Parent constructor with: Parent's String
1) Called Parent constructor with: Child's 1st String
2) Called Child constructor with: Child's 2nd String
Parent object has stored: Parent's String
Child object has stored: Child's 1st String
Child object has stored: Child's 2nd String


And that's just as we expect.

Wednesday, 9 February 2011

CPAN problem with Compress::Zlib

Perl Version:  5.8.4 
Operating System: OpenIndiana oi_148
Error Message(s) seen:
Undefined subroutine &Compress::Zlib::gzopen called at /usr/perl5/5.8.4/lib/CPAN/Tarzip.pm line 122


This error showed up while installing a module called Config::Crontab.  It potentially could have caused problems with installing any module though, as I'm pretty sure that it's down to missing dependencies for Compress::Zlib.

The error presented itself as follows:

 cpan[2]> install Config::Crontab
Running install for module 'Config::Crontab'
Running make for S/SC/SCOTTW/Config-Crontab-1.30.tar.gz
CPAN: LWP::UserAgent loaded ok (v5.835)
Fetching with LWP:
  ftp://mirror.ox.ac.uk/sites/www.cpan.org/authors/id/S/SC/SCOTTW/Config-Crontab-1.30.tar.gz
CPAN: Digest::SHA loaded ok (v5.50)
Fetching with LWP:
  ftp://mirror.ox.ac.uk/sites/www.cpan.org/authors/id/S/SC/SCOTTW/CHECKSUMS
Catching error: "Undefined subroutine &Compress::Zlib::gzopen called at /usr/perl5/5.8.4/lib/CPAN/Tarzip.pm line 122.\cJ" at /usr/perl5/5.8.4/lib/CPAN.pm line 391
    CPAN::shell() called at -e line 1

As this suggests a problem with Compress::Zlib, I tried to update it:
cpan[3]> install Compress::Zlib
Compress::Zlib is up to date (2.033).j

The solution was to remove Compress::Zlib and reinstall it, which then picked up missing dependencies and installed them:

root@ph_opensolaris:/root# ls /usr/perl5/site_perl/5.8.4/Compress/
Zlib.pm
root@ph_opensolaris:/root# rm /usr/perl5/site_perl/5.8.4/Compress/Zlib.pm

cpan[1]> install Compress::Zlib



Problems using CPAN / Perl Modules with OpenSolaris (& OpenIndiana)

Perl version: 5.8.4
Operating System: OpenIndiana oi_148 (I imagine that OpenSolaris also sees these problems)
Error Message(s) seen:  
cc: unrecognized option `-KPIC'
cc: language ildoff not recognized
cc: SHA.c: linker input file unused because linking not done
[...]
cc: SHA.o: No such file or directory
cc: no input files
Make had returned bad status, install seems impossible


The key errors here are the 'unrecognised option' and 'language not recognised' messages, which are coming from cc.  cc on OpenIndiana is a link from /usr/gnu/bin/cc to /usr/sfw/bin/gcc - and gcc is not recognising some of the flags that are passed to it.

 These are specified in this file:

/usr/perl5/5.8.4/lib/i86pc-solaris-64int/Config.pm

by the lines:

cccdlflags='-KPIC'

and,

optimize='-xO3 -xspace -xildoff'

To solve the problem, we need to remove (all) the offending entries, so that these two lines read:

cccdlflags=''

and,

optimize=''

Tuesday, 27 July 2010

Using perl (CGI.pm) to generate a meta refresh tag with start_html

Perl version: 5.8.4
Operating System: Solaris 10 (should be irrelevant)
Problem: It's irritatingly difficult to get perl to generate a refresh tag...


This should have been simple, but wasn't.  Sounds like a good topic for a quick blog post.


How to generate <meta http-equiv="refresh" content="5" /> in your header tag with Perl.pm:
print start_html(
      -head=>meta({-http_equiv => 'refresh',
        -content => '5' }),
          );


Easy.  If you found this with two minutes googling, feel the warm, satisfying glow of knowing that it took me about two hours to figure that one out.