OO Perl - How to maintain class state when using inherited methods?

OO Perl - How to maintain class state when using inherited methods?

Post by jeff_noke » Wed, 23 Aug 2006 16:53:08


Hi,
Here are a couple example class files:

#Collection.pm

package Collection;

our $ClassType = 'Collection_type'; # Class variable

sub new ($;) {
my($class_name) = @_;
my $self = {};
$self->{class_name} = __PACKAGE__;
$self->{property_1} = 'foo';
bless($self, $class_name);
return($self);
}# end new()


sub serializeObject($;) {
my($self) = @_;
my $serialized_object = $ClassType . ',' .
$self->{class_name} . ',' .
$self->{property_1};
return($serialized_object);
}# end serializeObject()


sub getClassType($;) {
return($ClassType);
}# end getClassType()

1;

----------------------------------

#Addresses.pm

package Addresses;

use Collection;

our @ISA = (
'Collection',
);

our $ClassType = 'Addresses_type'; # Class variable.

1;

-------------------------------

Test script:

perl -e 'use Data::Dumper; use Collection; use Addresses;'\
-e 'my $obj_addr = Addresses->new();'\
-e 'print("\n" . Dumper($obj_addr) . "\n" . '\
-e ' "Serialized Object = " . $obj_addr->serializeObject() .
"\n" . '\
-e ' "getClassTtype = " . $obj_addr->getClassType() . "\n"'\
-e ');'

--------------------------------

Output:

$VAR1 = bless( {
'class_name' => 'Collection',
'property_1' => 'foo'
}, 'Addresses' );

Serialized Object = Collection_type,Collection,foo
getClassTtype = Collection_type

---------------------------------------

Questions:

(1) Referencing the dumped object in the above output, I can see that
the namespace of the object is 'Addresses', but all of the internal
properties are that of the parent class Collection.pm. Is it that the
namespace was set to 'Addresses' simply due to the arrow notation
implicitly invoking the parent class' new() method? And the object
really has Collection properties because Perl already walked up the ISA
tree into the Collection namespace?

(2) Both classes have the same class level variable $ClassType. Even
though the namespace of the $obj_addr is 'Addresses', when invoking the
inherited method getClassType(), the output still reflects that of the
parent class' $ClassType? Why? Again, has Perl already walked up the
ISA tree to execute this inherited method, and therefore it sees the
namespace 'Collection' vice 'Addresses'?

(3) If I want to keep Addresses level stateful data inside the object,
is the proper way to do so to pass the data into the inherited
constuctor as arguments?

example:

$obj_addr = Addresses->new($Addresses::ClassType);

Collection.pm: new()
------------
sub new ($;$) {
my($class_name, $stateful_data) = @_;
my $self = {};
$self->{data_type} = $stateful_data;
bless($self, $class_name);
return($self);
}# end new()


I feel like I'm missing some basic premis, that this should be able to
be done without the explicit need to pass the data into the inherited
constructor. Does anyone have any suggestions on how to achieve this
differenlty then my example above?

Thanks in advance for any advice you can offer.

- J.
 
 
 

OO Perl - How to maintain class state when using inherited methods?

Post by Mumia W » Wed, 23 Aug 2006 18:27:28

n 08/22/2006 02:53 AM, XXXX@XXXXX.COM wrote:

Yes


Yes


No


This is better:
$self->{data_type} = __PACKAGE__;



Read "perldoc perltooc" and possibly use Class::Data::Inheritable.

 
 
 

OO Perl - How to maintain class state when using inherited methods?

Post by anno400 » Wed, 23 Aug 2006 19:11:00

< XXXX@XXXXX.COM > wrote in comp.lang.perl.misc:

Methods don't honor prototypes. Don't use them with methods, it's only
confusing.


This is messy. The class your object is blessed into is $class_name.
Smuggling the original class name into the object via __PACKAGE__ won't
(and shouldn't) change that. Finding "Collection" as the alleged
"class_name" of an object that is blessed somewhere else can only
be confusing. Use ref() to find the class of an object.


The term "namespace" is misleading here. Objects have a *class* which
is a package and hence a name space in some sense. But that doesn't
mean the object will use the package it is blessed into for accessing
package variables. Package variables work exactly as the always work.
What they access is determined at compile time, it doesn't matter
which object uses them.


That's what happens. Since the new() method in Collection correctly
blesses an object into the class it is invoked through (Addresses), what
you get it an Addresses object created by the Collection::new method.
That is how it should be.


I don't know what you mean by that.


When the method getClassType was compiled, the variable
$Collection::ClassType was compiled in. That doesn't change, even if
the method is later invoked through an object of a different class.


I don't think so.

Just define a getClassType method in Addresses that accesses the intended
package variable ($Addresses::ClassType) and overrides the one from
Collection.

As far as I can see the values "Collection_type" and "Address_type"
won't change during the program run. You could as well do away with
the package variables and use constant methods:

sub getClassType { 'Collection_type' } # in Collection.pm
sub getClassType { 'Address_type' } # in Address.pm

Anno