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

Discussion in 'Perl Misc' started by jeff_nokes@yahoo.com, Aug 22, 2006.

  1. Guest

    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.
    , Aug 22, 2006
    #1
    1. Advertising

  2. Mumia W. Guest

    On 08/22/2006 02:53 AM, wrote:
    > 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?
    >


    Yes

    > (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'?
    >


    Yes

    > (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?
    >


    No

    > example:
    >
    > $obj_addr = Addresses->new($Addresses::ClassType);
    >
    > Collection.pm: new()
    > ------------
    > sub new ($;$) {
    > my($class_name, $stateful_data) = @_;
    > my $self = {};
    > $self->{data_type} = $stateful_data;


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


    > 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.
    >


    Read "perldoc perltooc" and possibly use Class::Data::Inheritable.
    Mumia W., Aug 22, 2006
    #2
    1. Advertising

  3. -berlin.de Guest

    <> wrote in comp.lang.perl.misc:
    > Hi,
    > Here are a couple example class files:
    >
    > #Collection.pm
    >
    > package Collection;
    >
    > our $ClassType = 'Collection_type'; # Class variable
    >
    > sub new ($;) {


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

    > my($class_name) = @_;
    > my $self = {};
    > $self->{class_name} = __PACKAGE__;


    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.

    > $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.


    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.

    > Is it that the
    > namespace was set to 'Addresses' simply due to the arrow notation
    > implicitly invoking the parent class' new() method?


    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.

    > And the object
    > really has Collection properties because Perl already walked up the ISA
    > tree into the Collection namespace?


    I don't know what you mean by that.

    > (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'?


    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.

    > (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?


    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
    -berlin.de, Aug 22, 2006
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. David Berman
    Replies:
    2
    Views:
    4,687
    David Berman
    Feb 3, 2005
  2. Tron Thomas
    Replies:
    10
    Views:
    1,060
    Tom Widmer
    Nov 10, 2004
  3. Replies:
    4
    Views:
    376
  4. 7stud --
    Replies:
    11
    Views:
    387
    7stud --
    Nov 9, 2007
  5. Kenneth McDonald
    Replies:
    5
    Views:
    301
    Kenneth McDonald
    Sep 26, 2008
Loading...

Share This Page