OOP in Perl


Ein Beispiel in C++

Folgendes Beispiel zeigt ein Array, das seine Indizes zur Laufzeit überprüft. Ok, in Perl ist so etwas nicht nötig, weil dort Arrays selbstständig wachsen. Dennoch wird dieses Beispiel weiter unten in Perl umkodiert. Es geht darum zu zeigen, wie OOP-Elemente, die aus C++ bekannt sind, in Perl umgesetzt werden können.
// c++-example.cc -- a simple example of a c++ program
// (c) 1997/01/27 by Farid Hajji

#include <iostream.h>

// ----------- class definitions ---------------------------
// definition of base class
class Base {
protected:
  int a_base;         // a data-element from the base class
  char *buf;          // a buffer, dynamically allocated

public:
  static int counter; // a static counter

public:
  Base(char *contents, int val1=0);     // constructor
  ~Base();                              // destructor
  void set(char *newcontents);   // a method
  char *get(void);               // another method
  void display(void);            // print contents
};

// definition of a derived class
class Derived : public Base {
  int a_derived;    // a new derived element

public:
  Derived(char *contents, int val1=0, int val2=0);
  ~Derived();
  void display(void);            // override display()
};

// static behavious
int Base::counter = 0;           // setup static variable

// ----------- method definitions ---------------------------

// method definitions of Base
Base::Base(char *c, int v) {
  buf = new char[strlen(c)+1];
  strcpy(buf, c);
  a_base = v;
  counter++;
}

Base::~Base() {
  delete buf;
  counter--;
}

void Base::set(char *nval) {
  delete buf;
  buf = new char[strlen(nval)+1];
  strcpy(buf, nval);
}

char * Base::get(void) {
  return buf;
}

void Base::display(void) {
  cout << "Base: Text=(" << buf
       << "), Value 1= " << a_base
       << "\n";
}

// method definitions of Derived
Derived::Derived(char *contents,
                 int val1, int val2)
  : Base(contents, val1) {
    a_derived = val2;
}

Derived::~Derived() {}
// nothing to do here
// the destructor Base::~Base() will do all necessary work

void Derived::display(void) {
  cout << "Derived: Text=(" << buf
       << "), Value 1= "    << a_base
       << ", Value 2= "     << a_derived
       << "\n";
}

// ----------- main routine --------------------------------
int main(void) {
  Base b1("first val", 4711);
  Base b2("second val", 1111);
  Base *bptr = new Base("dynamic val");   // value: 0

  Derived d1("derived val1", 1234, 9876);
  Derived d2("derived val2", 4444);
  Derived d3("derived val3");
  Derived *dptr = new Derived("Dynval", 9999, 8888);

  b1.display();
  b2.display();
  bptr->display();

  cout << "Contents of b2: " << b2.get() << "\n";
  bptr->set("Another Value");
  bptr->display();

  d2.display();
  dptr->set("xyzzy");
  dptr->display();

  cout << "All Objekts: " << Base::counter << "\n";

  delete bptr;
  delete dptr;

  cout << "Remaining Objects: " << Base::counter << "\n";

  return 0;       // call of destructor for remaining objs.
}

Das gleiche Beispiel in Perl

#!/usr/local/bin/perl -w
# perl++-example.pl -- perl's equivalent of c++-example.cc
# demo of perl's OOP constructs
# (c) 1997/01/27 by Farid Hajji

use strict;

# ----------------------- BASE ------------------------------
package Base;

local($Base::counter);                 # NOT my(counter) !!!
 
sub new {
    my $class = shift;           # get package name (Base)
    my $self  = {};              # create a namespace for
                                 # this Base-instance
    # initialize the elements
    $self->{'buf'}    = shift;   # fill in the buffer
    $self->{'a_base'} = shift;   # fill in data element
    $Base::counter++;            # actually Base::counter

    # default behaviour: a_base =0 if not actually specified
    $self->{'a_base'} = 0
          if not defined $self->{'a_base'};

    # activate the object
    bless($self, $class);        # return value is reference
}

sub set {
    my $self   = shift;          # virtual method. get instance
    my $newval = shift;          # get normal parameter

    $newval = 0 if not defined($newval);  # val1=0 default
    $self->{'buf'} = $newval;    # save a new value
}

sub get {
    my $self   = shift;          # virtual method. get instance

    $self->{'buf'};              # return value of buffer
}

sub display {
    my $self   = shift;          # virtual method. get instance

    print "Base:: " .
          "Buffer: (" . $self->{'buf'} . "), " .
          "Value1: (" . $self->{'a_base'} . ")\n";
}

END { $Base::counter--; }        # the destructor of Base.

# ------------------------ DERIVED -------------------------
package Derived;

use vars qw(@ISA);
@ISA =   qw(Base);          # inherited from 'Base'

sub new {
    my $class =  shift;     # get name of class 'Derived'
    my $bufval = shift;     # get normal parameters
    my $val1   = shift;
    my $val2   = shift;

    $val1 = 0 if not defined $val1;   # default =0
    $val2 = 0 if not defined $val2;   # default =0

    my $self = Base->new($bufval, $val1); # call constructor
                                          # of Base
                            # (increments $Base::counter)
                            # ($self is already blessed Base)

    $self->{'a_derived'} = $val2;     # add an data element
                                      # to Namespace

    bless($self, $class);   # make it magical
                            # must be last expression here
}

sub display {
    my $self = shift;       # virtual method. get instance

    print "Derived:: " .
          "Buffer: (" . $self->{'buf'} . "), " .
          "Values: (" . $self->{'a_base'} . "," .
                        $self->{'a_derived'} . ")\n";
}

# no destructor necessary in Derived


# ------------------------ MAIN ----------------------------
package main;               # back to main's package

my $b1 = Base->new("first val", 4711);
my $b2 = Base->new("second val", 1111);
my $bptr = Base->new("dynamic val");

my $d1 = Derived->new("derived val1", 1234, 9876);
my $d2 = Derived->new("derived val2", 4444);
my $d3 = Derived->new("derived val3");
my $dptr = Derived->new("Dynval", 9999, 8888);

$b1->display();
$b2->display();
$bptr->display();

print "B2 contents: "; print $b2->get(); print "\n";

$bptr->set("Another Value");
$bptr->display();

$d2->display();
$dptr->set("xyzzy");
$dptr->display();

print "All Objekts: " . $Base::counter . "\n";

Namenshash

Da alle Objekte(-Instanzen) unterschiedliche Datenelemente haben, müssen wir Anonyme Hashes zur Speicherung dieser Datenelemente verwenden:

Vorherige Seite, Nächste Seite, Index, Hauptindex.


Copyright © 1997/08/16 by Farid Hajji.