Calendar
数据载入中,请稍候......
Placard
数据载入中,请稍候......
Category
数据载入中,请稍候......
Latest Entries
数据载入中,请稍候......
Latest Comments
数据载入中,请稍候......
Last Messages
数据载入中,请稍候......
User Login
数据载入中,请稍候......
Links
Information
数据载入中,请稍候......
Search
Other


Welcome to my blog!
  超难面向对象perl编程......
 

ObjectTemplate.pm

===================================================

package ObjectTemplate;

require Exporter;

@ObjectTemplate::ISA = qw(Exporter);

@ObjectTemplate::EXPORT = qw(attributes);

 

my $debugging = 1; # assign 1 to it to see code generated on the fly

 

# Create accessor functions, and new()

sub attributes {

    my ($pkg) = caller(0);

    @{"${pkg}::_ATTRIBUTES_"} = @_;

    my $code = "";

    foreach my $attr (get_attribute_names($pkg)) {

        # If a field name is "color", create a global list in the

        # calling package called @color

        @{"${pkg}::_$attr"} = ();

 

        # Define accessor only if it is not already present

        unless ($pkg->can("$attr")) {

            $code .= _define_accessor ($pkg, $attr);

        }

    }

    $code .= _define_constructor($pkg);

    eval $code;

    if ($@) {

       die  "ERROR defining constructor and attributes for '$pkg':"

            . "\n\t$@\n"

            . "-----------------------------------------------------"

            . $code;

    }

}

 

# $obj->set_attributes (name => 'John', age => 23);

# Or, $obj->set_attributes (['name', 'age'], ['John', 23]);

sub set_attributes {

    my $obj = shift;

    my $attr_name;

    if (ref($_[0])) {

       my ($attr_name_list, $attr_value_list) = @_;

       my $i = 0;

       foreach $attr_name (@$attr_name_list) {

            $obj->$attr_name($attr_value_list->[$i++]);

       }

    } else {

       my ($attr_name, $attr_value);

       while (@_) {

           $attr_name = shift;

           $attr_value = shift;

           $obj->$attr_name($attr_value);

       }

    }

}

 

 

# @attrs = $obj->get_attributes (qw(name age));

sub get_attributes {

    my $obj = shift;

    my (@retval);

    map $obj->${_}(), @_;

}

 

 

sub get_attribute_names {

    my $pkg = shift;

    $pkg = ref($pkg) if ref($pkg);

    my @result = @{"${pkg}::_ATTRIBUTES_"};

    if (defined (@{"${pkg}::ISA"})) {

        foreach my $base_pkg (@{"${pkg}::ISA"}) {

           push (@result, get_attribute_names($base_pkg));

        }

    }

    @result;

 

}

 

sub set_attribute {

    my ($obj, $attr_name, $attr_value) = @_;

    my ($pkg) = ref($obj);

    ${"${pkg}::_$attr_name"}[$$obj] = $attr_value;

}

 

sub get_attribute {

    my ($obj, $attr_name, $attr_value) = @_;

    my ($pkg) = ref($obj);

    return ${"${pkg}::_$attr_name"}[$$obj];

}

 

 

sub DESTROY {

    # release id back to free list

    my $obj = $_[0];

    my $pkg = ref($obj);

    local *_free = *{"${pkg}::_free"};

    my $inst_id = $$obj;

    # Release all the attributes in that row

    local(*attributes) = *{"${pkg}::_ATTRIBUTES_"};

    foreach my $attr (@attributes) {

        undef ${"${pkg}::_$attr"}[$inst_id];

    }

    $_free[$inst_id] = $_free;

    $_free = $inst_id;

}

 

sub initialize { }; # dummy method, if subclass doesn’t define one.

 

#################################################################

 

sub _define_constructor {

    my $pkg = shift;

    my $code = qq {

        package $pkg;

        sub new {

            my \$class = shift;

            my \$inst_id;

            if (defined(\$_free[\$_free])) {

                \$inst_id = \$_free;

                \$_free = \$_free[\$_free];

                undef \$_free[\$inst_id];

            } else {

                \$inst_id = \$_free++;

            }

            my \$obj = bless \\\$inst_id, \$class;

            \$obj->set_attributes(\@_) if \@_;

            \$obj->initialize;

            \$obj;

 

        }

    };

    $code;

}

 

sub _define_accessor {

    my ($pkg, $attr) = @_;

 

    # This code creates an accessor method for a given

    # attribute name. This method  returns the attribute value

    # if given no args, and modifies it if given one arg.

    # Either way, it returns the latest value of that attribute

 

 

    # qq makes this block behave like a double-quoted string

    my $code = qq{

        package $pkg;

        sub $attr {                                      # Accessor ...

            \@_ > 1 ? \$_${attr} \[\${\$_[0]}] = \$_[1]  # set

                    : \$_${attr} \[\${\$_[0]}];          # get

        }

        if (!defined \$_free) {

            # Alias the first attribute column to _free

            \*_free = \*_$attr;

            \$_free = 0;

        };

 

    };

    $code;

}

 

1;

 

 

Employee.pm

=====================================================

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

package Employee;

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

# This package uses the ObjectTemplate package to declare an Employee object

#

#

# It consists

use ObjectTemplate;

@ISA = qw(ObjectTemplate);

&attributes qw(name age sex);

 

sub print {

    my $obj = $_[0];

    print "Employee[$$obj] ...  Free index: $_free\n";

    print "\tName   => ", $obj->name  ,"\n";

    print "\tAge    => ", $obj->age   ,"\n";

}

 

sub name {

    # Example of a custom accessor function

    # Allows the name attribute to be set only once

    my $obj = shift;

    my $name = $obj->get_attribute("name");

 

    if (@_) {

       if ($name) {

          die "Cannot update name \n";

       } else {

          $obj->set_attribute("name", $_[0]);

       }

    }

    $name;

}

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

# Sample inherited Class

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

 

package HourlyEmployee;

@ISA = qw (Employee);

use ObjectTemplate;

attributes qw(wage);

 

 

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

# TESTING CODE

#    Simply invoke as "perl Employee.pm"

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

 

if (! caller()) {

 

    package main;

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

    # Check create

    $e1 = Employee->new(name => 'test1', age  => 43);

    $e2 = Employee->new(name => 'test2', age  => 50);

    if ($e1->name ne 'test1' || $e2->age != 50) {

        print "ERROR. Accessors not working\n";

    } else {

        print "OK. Accessors working\n";

    }

 

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

    # Check that deleting one object doesn't mess the other

    undef $e1;

 

    if ($e2->name ne 'test2' || $e2->age != 50) {

        print "ERROR ... Delete messing up other objects\n";

    } else {

        print "OK. Delete doesn't affect other objects\n";

    }

 

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

    # Check creation of object after delete

    $e1 = Employee->new(name => 'test1', age  => 43);

    if ($e1->name ne 'test1' || $e2->age != 50) {

        print "ERROR .... Object not created correctly after delete\n";

    } else {

        print "OK. Object created correctly after delete\n";

    }

 

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

    # Check if custom accessor called

    eval {$e1->name("foo")};

    if ($@ !~ /Cannot update name/) {

        print "ERROR. Custom accessor not called\n";

    } else {

        print "OK. Custom accessor called\n";

    }

 

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

    # Check if inherited properly

    $e2 = HourlyEmployee->new(name => 'Joe', age => 47, wage => 40);

    if ($e2->name ne 'Joe' || $e2->age != 47) {

        print "ERROR. Accessors of inherited classes not working\n";

    } else {

        print "OK. Accessors of inherited classes working\n";

    }

 

    eval {$e2->name("foo")};

    if ($@ !~ /Cannot update name/) {

        print "ERROR. Inherited custom accessor not called\n";

    } else {

        print "OK. Inherited custom accessor works\n";

    }

 

 

}

1;

Test.pl

#!/usr/bin/perl -w

 

use Employee;

use Benchmark;

 

package HashEmp;

sub new {

   bless {name => 'ram', age => 23};

}

sub age {

   $_[0]->{age};

}

 

package main;

$o  = Employee->new(name => "ram", age => 32);

$o1 = HashEmp->new();

print ref($_);

print $o->age, " ", $o1->{age},"\n";

 

# Measure speed of accessors for  objects built using ObjectTemplate

# and an ordinary hash

timethese (100000,

   {"Employee", '$x = $o->age',

    "HashEmp" , '$x = $o1->age'

   }

);

[ 阅读全文 | 回复(0) | 引用通告 | 编辑

  Post  by  badboy 发表于 2007-12-29 11:23:00
发表评论:
数据载入中,请稍候......
数据载入中,请稍候......