Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

copy contructor

6 views
Skip to first unread message

Moritz Karbach

unread,
Jul 15, 2005, 6:53:49 AM7/15/05
to
Hi,

I'm writing some code in object oriented Perl, and I'm missing a default
copy constructor. Are there some default workarounds?

I heard somewhere, that there is an array or a hash containing all names of
the variables of a class / package. Can't remember how it was called. Maybe
one could use this to copy the attributes?

Cheers,

- Moritz

Paul Lalli

unread,
Jul 15, 2005, 8:03:27 AM7/15/05
to
Moritz Karbach wrote:
> I'm writing some code in object oriented Perl, and I'm missing a default
> copy constructor. Are there some default workarounds?

I don't have my Camel on me, but ISTR the chapter on overloading talks
about overloading the = operator as a copy constructor. This copy
constructor is called by *other* overloaded operators that somehow
"know" a copy is needed.

If you really just want to write a subroutine to copy an object, I
would suggest looking into the dclone() function of the Storable
module, or the Clone module available on CPAN.

> I heard somewhere, that there is an array or a hash containing all names of
> the variables of a class / package. Can't remember how it was called. Maybe
> one could use this to copy the attributes?

You're talking about the symbol table. The symbol table can be
accessed as a hash variable named by the package name followed by two
colons. So package Foo's symbol table is:
%{Foo::}
By inspecting the keys of this hash, you could find the name of all the
package variables and subroutines the package contains. (Note that a
simple inspection of this hash will not reveal the variables'
values.... search the perldocs for "typeglobs" for more information on
those...)

Paul Lalli


>
> Cheers,
>
> - Moritz

Anno Siegel

unread,
Jul 15, 2005, 8:21:10 AM7/15/05
to
Moritz Karbach <moritz....@desy.de> wrote in comp.lang.perl.misc:

> Hi,
>
> I'm writing some code in object oriented Perl, and I'm missing a default
> copy constructor. Are there some default workarounds?

Huh? Standard OO doesn't know about copy constructors. They come
into play with operator overloading, but even then you don't necessarily
have to define one. You *can* use one to give overloaded mutators
like "+=" the expected semantics, but that's a subtlety.

> I heard somewhere, that there is an array or a hash containing all names of
> the variables of a class / package. Can't remember how it was called. Maybe
> one could use this to copy the attributes?

What do attributes have to do with it?

A package My::Package has a so-called stash %My::Package:: associated with
it. Its keys are the names of symbols that are defined in the package,
its values are the corresponding typeglobs. So "print "$_\n" for
keys %main::;" prints all the symbols in package main. But for the
life of me I don't see what this has to do with a copy constructor.

Anno
--
If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.

A. Sinan Unur

unread,
Jul 15, 2005, 8:40:48 AM7/15/05
to
Moritz Karbach <moritz....@desy.de> wrote in
news:db84k9$d4ib$1...@claire.desy.de:

> I'm writing some code in object oriented Perl, and I'm missing a
> default copy constructor. Are there some default workarounds?

As others have pointed out, I am not sure how you came up with the
requirement to have a copy constructor.

Do read about dclone in
<URL:http://search.cpan.org/~ams/Storable-2.15/Storable.pm>

For a discussion involving copy constructors, see:

<URL: http://groups-beta.google.com/group/comp.lang.perl.misc/browse_frm/thread/bf268f7ea3127db5/c6df928063204559?tvc=1&q=copy+constructor+group:comp.lang.perl.misc&hl=en#c6df928063204559>

Sinan
--
A. Sinan Unur <1u...@llenroc.ude.invalid>
(reverse each component and remove .invalid for email address)

comp.lang.perl.misc guidelines on the WWW:
http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html

T Beck

unread,
Jul 15, 2005, 10:14:06 AM7/15/05
to
"A. Sinan Unur" <1...@llenroc.ude.invalid> wrote:

> I'm writing some code in object oriented Perl, and I'm missing a
> default copy constructor. Are there some default workarounds?


As others have pointed out, I am not sure how you came up with the
requirement to have a copy constructor.


For those of you not getting this, C++ provides you with a copy
constructor by default. The concept is, if you have an object, it's
usually a good idea to know how to copy it. It's one of the big 3.
Copy Constructor, Overloaded = operator, and a destructor. (google the
law of the big three, if you're interested, which I note you're
probably not)
In Java this isn't as much the case... you have to make something
cloneable before you can give it a clone() function, which serves as
the copy constructor (more or less..)

Now my experience with Perl in OO is pretty limited, so I can't speak
to whether or not copy constructors are good or bad (or neither) in
Perl, but if you're coming from C++, you certainly expect to see at
least a default copy constructor, if nothing else.

Moritz Karbach

unread,
Jul 15, 2005, 10:51:18 AM7/15/05
to
>> I'm writing some code in object oriented Perl, and I'm missing a default
>> copy constructor. Are there some default workarounds?
>
> Huh? Standard OO doesn't know about copy constructors. They come
> into play with operator overloading, but even then you don't necessarily
> have to define one.

You're right. But IIRC at least C++ copies all attributes (or class members
or how you call it) of a class, if you say

Class1 object1;
Class1 object2;

/* modify members of object2... */

object1 = object2;

using the "standard copy constructor".


But nevertheless, my problem is simply the following: I've got a class with
about 50 attributes, and I need to get a exact clone of an object of this
class.

Therefore I've written a clone() method like

sub clone # ()
{
my $this = shift;
my $clone = new ClassName();

$clone->{att1} = $this->{att1};

# ...

@{$clone->{arr1}} = @{$this->{arr1}};

# ...

%{$clone->{hash1}} = %{$this->{hash1}};

return $clone;
}

Since this gets really huge and I'll also have to adjust this if I'm going
to add some new attributes, I was looking for an alternative a little more
sexy.

Cheers,

- Moritz

Paul Lalli

unread,
Jul 15, 2005, 11:18:30 AM7/15/05
to
Moritz Karbach wrote:
> >> I'm writing some code in object oriented Perl, and I'm missing a default
> >> copy constructor. Are there some default workarounds?
> >
> > Huh? Standard OO doesn't know about copy constructors. They come
> > into play with operator overloading, but even then you don't necessarily
> > have to define one.
>
> You're right. But IIRC at least C++ copies all attributes (or class members
> or how you call it) of a class, if you say
>
> Class1 object1;
> Class1 object2;
>
> /* modify members of object2... */
>
> object1 = object2;
>
> using the "standard copy constructor".

It's been a while since I did C++, but doesn't this only do shallow
copies of any pointers within the object?

So how is this different than just assigning the object to a new
variable in Perl?

my $newobj = $oldobj;

> But nevertheless, my problem is simply the following: I've got a class with
> about 50 attributes, and I need to get a exact clone of an object of this
> class.
>
> Therefore I've written a clone() method like

<snip>

That's what I don't get. Other messages in this thread have already
pointed you to two modules that do this for you. Why would you want to
write one yourself? Especially one that's less extensible?

Paul Lalli

Moritz Karbach

unread,
Jul 15, 2005, 1:59:51 PM7/15/05
to
Paul Lalli wrote:

> Why would you want to
> write one yourself?

Actually I had written it before I asked here :-) Surely I will have a look
at this module.

Cheers,

- Moritz

Tad McClellan

unread,
Jul 15, 2005, 4:33:36 PM7/15/05
to
Paul Lalli <mri...@gmail.com> wrote:
> Moritz Karbach wrote:
>> >> I'm writing some code in object oriented Perl, and I'm missing a default
>> >> copy constructor. Are there some default workarounds?

>> object1 = object2;


>>
>> using the "standard copy constructor".

> So how is this different than just assigning the object to a new


> variable in Perl?
>
> my $newobj = $oldobj;


There is only one object there (with 2 ways to access it).

(assuming assignment has not been overloaded)

A "copy" implies that there are two separate objects (that just
happen to contain identical data).


--
Tad McClellan SGML consulting
ta...@augustmail.com Perl programming
Fort Worth, Texas

A. Sinan Unur

unread,
Jul 16, 2005, 8:24:18 AM7/16/05
to
"T Beck" <Tracy...@Infineon.com> wrote in
news:1121436846.8...@f14g2000cwb.googlegroups.com:

Misquoted me as having said:

> "A. Sinan Unur" <1...@llenroc.ude.invalid> wrote:
>
>> I'm writing some code in object oriented Perl, and I'm missing a
>> default copy constructor. Are there some default workarounds?

Learn to quote properly, and get a proper newsreader, before professing.
I never said the above. You are lying. Lying is not good.

> As others have pointed out, I am not sure how you came up with the
> requirement to have a copy constructor.

I know, I do not.

> For those of you not getting this,

and for you,

*PLONK*
*PLONK* *PLONK*
*PLONK* *PLONK* *PLONK* *PLONK* *PLONK* *PLONK* *PLONK*

There. *Sigh*

Abigail

unread,
Jul 17, 2005, 6:19:28 PM7/17/05
to
Moritz Karbach (moritz....@desy.de) wrote on MMMMCCCXXXVI September
MCMXCIII in <URL:news:db8ihi$d616$1...@claire.desy.de>:
[] >> I'm writing some code in object oriented Perl, and I'm missing a default

[] >> copy constructor. Are there some default workarounds?
[] >
[] > Huh? Standard OO doesn't know about copy constructors. They come
[] > into play with operator overloading, but even then you don't necessarily
[] > have to define one.
[]
[] You're right. But IIRC at least C++ copies all attributes (or class members
[] or how you call it) of a class, if you say

Yeah, C++ has. But then, C++ has attributes, Perl doesn't. Perl has the
least language support I've ever seen for doing OO - it doesn't even have
attributes.

And the step from "no attributes" to "no functionality to copy attributes"
is trivial.


My advice: if you really want to do OO, use a different language.

Abigail
--
$_ = "\x3C\x3C\x45\x4F\x54\n" and s/<<EOT/<<EOT/ee and print;
"Just another Perl Hacker"
EOT

Anno Siegel

unread,
Jul 17, 2005, 7:11:46 PM7/17/05
to
Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:

> Moritz Karbach (moritz....@desy.de) wrote on MMMMCCCXXXVI September
> MCMXCIII in <URL:news:db8ihi$d616$1...@claire.desy.de>:
> [] >> I'm writing some code in object oriented Perl, and I'm missing a default
> [] >> copy constructor. Are there some default workarounds?
> [] >
> [] > Huh? Standard OO doesn't know about copy constructors. They come
> [] > into play with operator overloading, but even then you don't necessarily
> [] > have to define one.
> []
> [] You're right. But IIRC at least C++ copies all attributes (or class members
> [] or how you call it) of a class, if you say
>
> Yeah, C++ has. But then, C++ has attributes, Perl doesn't. Perl has the
> least language support I've ever seen for doing OO - it doesn't even have
> attributes.
>
> And the step from "no attributes" to "no functionality to copy attributes"
> is trivial.
>
>
> My advice: if you really want to do OO, use a different language.

The problem isn't so much that real OO couldn't be done in Perl, but
that what the language lacks in support must be supplied by the programmer,
and it can be supplied in various incompatible ways. This is a point
where Perl's TIMTOWTDI becomes a problem.

A lot would be gained if the role of accessors in Perl OO were better
appreciated. Any method that de-references its object is an accessor,
and an (inheriting) client class may have to override all of them. So it
needs to know which they are, and it is good to restrict them in number.

Usually that only means to define a few field accessors in the usual way,
and then *base all other methods on them*. There is much so-called Perl OO
code about that accesses the object all over the place and is almost
impossible to inherit from. More complex accessors are sometimes wanted
for efficiency or flexibility. They must be clearly documented so that
a client class knows how to override them.

A parent class that is designed (and maintained) to these principles
can be safely and relatively painlessly inherited from even across
changes in implementation.

Abigail

unread,
Jul 17, 2005, 7:27:49 PM7/17/05
to
Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXXXVIII
September MCMXCIII in <URL:news:dbeoji$hd8$1...@mamenchi.zrz.TU-Berlin.DE>:
## Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:
## > Moritz Karbach (moritz....@desy.de) wrote on MMMMCCCXXXVI September
## > MCMXCIII in <URL:news:db8ihi$d616$1...@claire.desy.de>:
## > [] >> I'm writing some code in object oriented Perl, and I'm missing a default
## > [] >> copy constructor. Are there some default workarounds?
## > [] >
## > [] > Huh? Standard OO doesn't know about copy constructors. They come
## > [] > into play with operator overloading, but even then you don't necessarily
## > [] > have to define one.
## > []
## > [] You're right. But IIRC at least C++ copies all attributes (or class members
## > [] or how you call it) of a class, if you say
## >
## > Yeah, C++ has. But then, C++ has attributes, Perl doesn't. Perl has the
## > least language support I've ever seen for doing OO - it doesn't even have
## > attributes.
## >
## > And the step from "no attributes" to "no functionality to copy attributes"
## > is trivial.
## >
## >
## > My advice: if you really want to do OO, use a different language.
##
## The problem isn't so much that real OO couldn't be done in Perl, but

Oh, I never said OO couldn't be done in Perl. OO can be done in any
language. Witness the perl source, which is (mostly) OO written in
the C preprocessor macros ;-)

## that what the language lacks in support must be supplied by the programmer,
## and it can be supplied in various incompatible ways. This is a point
## where Perl's TIMTOWTDI becomes a problem.

Indeed. As Larry said, Perl's OO system was an excercise in in making
something as minimal as possible.

## A lot would be gained if the role of accessors in Perl OO were better
## appreciated. Any method that de-references its object is an accessor,
## and an (inheriting) client class may have to override all of them. So it
## needs to know which they are, and it is good to restrict them in number.

Accessors don't solve the fundamental problem OO in Perl has: lack of
attributes. Getting to the attributes isn't a problem - it's the (lack
of the) attributes that are the problem: most approaches to do OO in
Perl, including the de facto standard (refs to hashes) break encapsulation
as soon as you want to do inheritance.

## Usually that only means to define a few field accessors in the usual way,
## and then *base all other methods on them*. There is much so-called Perl OO
## code about that accesses the object all over the place and is almost
## impossible to inherit from. More complex accessors are sometimes wanted
## for efficiency or flexibility. They must be clearly documented so that
## a client class knows how to override them.

One can use the most beautiful accessors, and rigorously use accessors
all over the place (and nothing but accessors) - if your implementation
of objects is wrong (for instance, you're stuffing your attributes in
refs to hashes) encapsulation has to be broken to do inheritance.

## A parent class that is designed (and maintained) to these principles
## can be safely and relatively painlessly inherited from even across
## changes in implementation.

Any class that doesn't solve the attribute problem is (IMNHO) worthless.
No matter how many layers of sugarcoat in the form of accessors are being
used.

Abigail
--
# Perl 5.6.0 broke this.
%0=map{reverse+chop,$_}ABC,ACB,BAC,BCA,CAB,CBA;$_=shift().AC;1while+s/(\d+)((.)
(.))/($0=$1-1)?"$0$3$0{$2}1$2$0$0{$2}$4":"$3 => $4\n"/xeg;print#Towers of Hanoi

Anno Siegel

unread,
Jul 18, 2005, 6:11:39 AM7/18/05
to
Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:
> Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXXXVIII
> September MCMXCIII in <URL:news:dbeoji$hd8$1...@mamenchi.zrz.TU-Berlin.DE>:
> ## Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:

[Perl OO doesn't support attributes]

> ## > And the step from "no attributes" to "no functionality to copy attributes"
> ## > is trivial.
> ## >
> ## >
> ## > My advice: if you really want to do OO, use a different language.
> ##
> ## The problem isn't so much that real OO couldn't be done in Perl, but
>
> Oh, I never said OO couldn't be done in Perl. OO can be done in any
> language. Witness the perl source, which is (mostly) OO written in
> the C preprocessor macros ;-)

Oh sure. You can do that without any support from the language. Just
like it was noted early on that you can write structured programs in
assembler and Fortran with just a little discipline.

> ## that what the language lacks in support must be supplied by the programmer,
> ## and it can be supplied in various incompatible ways. This is a point
> ## where Perl's TIMTOWTDI becomes a problem.
>
> Indeed. As Larry said, Perl's OO system was an excercise in in making
> something as minimal as possible.
>
> ## A lot would be gained if the role of accessors in Perl OO were better
> ## appreciated. Any method that de-references its object is an accessor,
> ## and an (inheriting) client class may have to override all of them. So it
> ## needs to know which they are, and it is good to restrict them in number.
>
> Accessors don't solve the fundamental problem OO in Perl has: lack of
> attributes.

But they do, or, if they don't solve the problem, they isolate it and
allow to work around it.

> Getting to the attributes isn't a problem - it's the (lack
> of the) attributes that are the problem:

I'm not sure what you mean here. Getting to the attributes which don't
exist anyway isn't a problem?

> most approaches to do OO in
> Perl, including the de facto standard (refs to hashes) break encapsulation
> as soon as you want to do inheritance.

Well yes, if you do what I like to call "inheritance by usurpation": Take
the parent object as it is and implant your own fields in it. That
allows you to inherit the fields of the parent class (that is, you
inherit the accessors, and they work with your objects), but indeed it
breaks encapsulation in a major way.

This style can only be used when two or more classes are developed and
maintained together and are not expected to part ways ever. For a
public class, the style is useless.

> ## Usually that only means to define a few field accessors in the usual way,
> ## and then *base all other methods on them*. There is much so-called Perl OO
> ## code about that accesses the object all over the place and is almost
> ## impossible to inherit from. More complex accessors are sometimes wanted
> ## for efficiency or flexibility. They must be clearly documented so that
> ## a client class knows how to override them.
>
> One can use the most beautiful accessors, and rigorously use accessors
> all over the place (and nothing but accessors) - if your implementation
> of objects is wrong (for instance, you're stuffing your attributes in
> refs to hashes) encapsulation has to be broken to do inheritance.

I'm taking a slightly different view. Rule one: In Perl OO, there are
no such things as attributes, their role is taken by accessors to the
object. Rule two: No accessor can be inherited from a base class,
it *must* be overridden in the inheriting class. All other (object)
methods can be inherited.

Following these rules, inheritance happens without breach of encapsulation,
and it is exactly clear what must be done to support it: Override all
accessors.

Of course, inheritance by usurpation is ruled out this way. The
inheriting class doesn't even know if the parent is implemented using
a hash ref.

> ## A parent class that is designed (and maintained) to these principles
> ## can be safely and relatively painlessly inherited from even across
> ## changes in implementation.
>
> Any class that doesn't solve the attribute problem is (IMNHO) worthless.
> No matter how many layers of sugarcoat in the form of accessors are being
> used.

In my opinion, class design around accessors does solve the attribute
problem. Whether the solution is satisfactory (generally, or for a
specific problem) is another question.

T Beck

unread,
Jul 18, 2005, 10:18:54 AM7/18/05
to
"A. Sinan Unur" <1...@llenroc.ude.invalid> wrote:
#THIS IS THE QUOTE> Learn to quote properly, and get a proper
newsreader, before professing.
#THIS IS THE QUOTE> I never said the above. You are lying. Lying is not
good.


Do those delimeters work? Because, I can add more symbols in...
symbols make ya happy?

I'm sorry, I just kind of assumed that... you know, in the presence of
right angle brackets, most people can grasp the context that you were
quoting someone else, and then responding. I hate that I mis-quoted
your quote, but if we get into meta-quoting semantics here, it's just
gonna drive me insane.

As for my reason: Ultimately, I post ~2 things to newsgroups per week,
while I'm at work. groups.google.com works fine for me. I sincerely
didn't mean to upset you with my quoting semantics, but I was just
dropping a quick note to stick up for the OP, who seems to be used to
writing in C++, and who seems to have caused about 7 people undue
irritation by merely {suggesting} that a copy constructor exist. I'll
try not to repeat the mistake again.

A. Sinan Unur

unread,
Jul 18, 2005, 2:16:14 PM7/18/05
to
"T Beck" <Tracy...@Infineon.com> wrote in
news:1121696334....@g44g2000cwa.googlegroups.com:

> "A. Sinan Unur" <1...@llenroc.ude.invalid> wrote:
> #THIS IS THE QUOTE> Learn to quote properly, and get a proper
> newsreader, before professing.
> #THIS IS THE QUOTE> I never said the above. You are lying. Lying is
> not good.
>
> Do those delimeters work? Because, I can add more symbols in...
> symbols make ya happy?

It is interesting what discoveries one can make by moving to a
different computer. I think I need a distributed killfile system.

I am not sure what part of "you attributed someone else's words
to me" you are unable to understand.

You did that in

<URL:http://groups-beta.google.com/group/comp.lang.perl.misc/msg/97d1c4736dc18aed>

The words you attributed to me in that message were not my words.

At least I get the pleasure of killfiling you on another computer.

> if we get into meta-quoting semantics here, it's just gonna drive
> me insane.

It is very simple. Don't say I said something I did not say. It
does not have anything to do with angle brackets.

*PLONK*

Abigail

unread,
Jul 18, 2005, 3:42:36 PM7/18/05
to
Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXXXIX
September MCMXCIII in <URL:news:dbfv8r$88k$1...@mamenchi.zrz.TU-Berlin.DE>:

[ Snip ]

&& In my opinion, class design around accessors does solve the attribute
&& problem. Whether the solution is satisfactory (generally, or for a
&& specific problem) is another question.


Just one question: how are you storing your attributes?


Abigail
--
perl5.004 -wMMath::BigInt -e'$^V=Math::BigInt->new(qq]$^F$^W783$[$%9889$^F47]
.qq]$|88768$^W596577669$%$^W5$^F3364$[$^W$^F$|838747$[8889739$%$|$^F673$%$^W]
.qq]98$^F76777$=56]);$^U=substr($]=>$|=>5)*(q.25..($^W=@^V))=>do{print+chr$^V
%$^U;$^V/=$^U}while$^V!=$^W'

T Beck

unread,
Jul 18, 2005, 4:40:22 PM7/18/05
to
I honestly never intended for this to turn into some kind of flame
war.. Yes, I got lazy and just copied your quote with borders of
spaces around it. Yes, when I checked, the main group view of google
groups properly colorized and made everything look like your quote (as
I intended it to). Yes, your quote also included you quoting someone
else. And finally, yes, it could be misconstrued that I was trying to
use your words in the same thread and make it look like you were the
OP. But it was a simple mistake.

Now, it's not a good idea to start out by calling me a liar. You make
it sound as though I've put libel about you out here. There was an
ambiguous quoting, don't get overworked. Also, I consider it extreme
(to say the least) to killfile someone for one little mistake. But
since you {did}, all I can say is, I hope you're slightly nicer to
people IRL, because if not, I'd hate to be your coworker.

That notwithstanding, I'm dropping this topic, because you seem to have
a hate on about it regardless...

Anno Siegel

unread,
Jul 18, 2005, 6:58:10 PM7/18/05
to
Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:
> Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXXXIX
> September MCMXCIII in <URL:news:dbfv8r$88k$1...@mamenchi.zrz.TU-Berlin.DE>:
>
> [ Snip ]
>
> && In my opinion, class design around accessors does solve the attribute
> && problem. Whether the solution is satisfactory (generally, or for a
> && specific problem) is another question.
>
>
> Just one question: how are you storing your attributes?

Any old way. The standard hash-as-a-record, its equivalent for
arrays, whatever the base type has to offer. The derived class
doesn't know, that's why it *has* to override all accessors.
If these are few and well known, the effort is expendable. The
rest of the class follows suit. You can well have an array class
inherit in this way from a hash class, and other combinations.

I'll give an example. In the code below, a class Parent has two
fields (attributes), alpha and beta. It also has the method total
which returns the sum of alpha and beta. It is implemented as
an array of two elements.

A class Client, implemented as the usual hash, wants to keep the role
of alpha, but split the field beta into the sum of its other fields
gamma and delta. It wants to inherit the ->total method from Parent,
which should thus be the sum of alpha, gamma and delta.

My point is that the method ->total, written to form the sum of a
two-element array, now forms the sum of a three-element hash.

Anno

#!/usr/local/bin/perl
use strict; use warnings; $| = 1;

my $c = Client->new( 5, 6, 7);
print "$_ -> ", $c->$_, "\n" for qw( alpha beta gamma delta total);

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

package Parent;

sub new {
my $class = shift;
my ( $alpha, $beta) = @_;
bless [ $alpha, $beta], $class;
}

sub alpha { $_[ 0]->[ 0] }
sub beta { $_[ 0]->[ 1] }

sub total { $_[ 0]->alpha + $_[ 0]->beta }


package Client;
BEGIN { our @ISA = 'Parent' }

sub new {
my $class = shift;
my ( $alpha, $gamma, $delta) = @_;
bless {
alpha => $alpha,
gamma => $gamma,
delta => $delta,
}, $class;
}

sub alpha { $_[ 0]->{ alpha} }
sub gamma { $_[ 0]->{ gamma} }
sub delta { $_[ 0]->{ delta} }

sub beta { $_[ 0]->gamma + $_[ 0]->delta }

__END__

Jürgen Exner

unread,
Jul 18, 2005, 8:10:31 PM7/18/05
to
T Beck wrote:
> I honestly never intended for this to turn into some kind of flame
> war.. Yes, I got lazy and just copied your quote with borders of

Who is "you"? Who are you talking to?
It is customary to quote appropriate context such that people have a chance
to know what you are talking about.

> spaces around it. Yes, when I checked, the main group view of google
> groups properly colorized and made everything look like your quote (as
> I intended it to).

What does Google have to do with anything except that they added a broken UI
for posting articles to their otherwise decend archive?

> Now, it's not a good idea to start out by calling me a liar. You make
> it sound as though I've put libel about you out here. There was an
> ambiguous quoting, don't get overworked. Also, I consider it extreme

Well, would be nice to be able to see that quoting and make my own judgement
call.
Too bad that you snipped it.

jue


Abigail

unread,
Jul 18, 2005, 8:30:00 PM7/18/05
to
Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXXXIX
September MCMXCIII in <URL:news:dbhc62$53b$1...@mamenchi.zrz.TU-Berlin.DE>:
:) Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:
:) > Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXXXIX
:) > September MCMXCIII in <URL:news:dbfv8r$88k$1...@mamenchi.zrz.TU-Berlin.DE>:
:) >
:) > [ Snip ]
:) >
:) > && In my opinion, class design around accessors does solve the attribute
:) > && problem. Whether the solution is satisfactory (generally, or for a
:) > && specific problem) is another question.
:) >
:) >
:) > Just one question: how are you storing your attributes?
:)
:) Any old way. The standard hash-as-a-record, its equivalent for
:) arrays, whatever the base type has to offer. The derived class
:) doesn't know, that's why it *has* to override all accessors.
:) If these are few and well known, the effort is expendable. The
:) rest of the class follows suit. You can well have an array class
:) inherit in this way from a hash class, and other combinations.
:)
:) I'll give an example. In the code below, a class Parent has two
:) fields (attributes), alpha and beta. It also has the method total
:) which returns the sum of alpha and beta. It is implemented as
:) an array of two elements.
:)
:) A class Client, implemented as the usual hash, wants to keep the role
:) of alpha, but split the field beta into the sum of its other fields
:) gamma and delta. It wants to inherit the ->total method from Parent,
:) which should thus be the sum of alpha, gamma and delta.
:)
:) My point is that the method ->total, written to form the sum of a
:) two-element array, now forms the sum of a three-element hash.
:)
:) Anno
:)
:) #!/usr/local/bin/perl
:) use strict; use warnings; $| = 1;
:)
:) my $c = Client->new( 5, 6, 7);
:) print "$_ -> ", $c->$_, "\n" for qw( alpha beta gamma delta total);
:)
:) ##########################################################################
:)
:) package Parent;
:)
:) sub new {
:) my $class = shift;
:) my ( $alpha, $beta) = @_;
:) bless [ $alpha, $beta], $class;
:) }
:)
:) sub alpha { $_[ 0]->[ 0] }
:) sub beta { $_[ 0]->[ 1] }
:)
:) sub total { $_[ 0]->alpha + $_[ 0]->beta }
:)
:)
:) package Client;
:) BEGIN { our @ISA = 'Parent' }
:)
:) sub new {
:) my $class = shift;
:) my ( $alpha, $gamma, $delta) = @_;
:) bless {
:) alpha => $alpha,
:) gamma => $gamma,
:) delta => $delta,
:) }, $class;
:) }
:)
:) sub alpha { $_[ 0]->{ alpha} }
:) sub gamma { $_[ 0]->{ gamma} }
:) sub delta { $_[ 0]->{ delta} }
:)
:) sub beta { $_[ 0]->gamma + $_[ 0]->delta }
:)
:) __END__


Well, that "works", but that kind of defeats the purpose of using OO:
reusing code. You will have to redefined *every* method of a parent class.
Take for instance the above example - since you aren't going to break
encapsulation, you don't know how the class is implemented. It might as
well be:


package Parent;

sub new {
my $class = shift;
my ( $alpha, $beta) = @_;

bless [ $alpha, $beta, $alpha + $beta ], $class;


}

sub alpha { $_[ 0]->[ 0] }
sub beta { $_[ 0]->[ 1] }

sub total { $_[ 0]->[ 2] }


It has the same interface, but if you now create your Client class
as presented, calling the method 'total' results in "Not an ARRAY reference".

You have to redefine any method that touches an attribute directly - and
you either have to peek inside (breaking encapsulation) to know which
methods touch an attribute - or redefine every method.

But if you redefine every method, what's the point of inheritance?

Abigail
--
perl -wle '$, = " "; sub AUTOLOAD {($AUTOLOAD =~ /::(.*)/) [0];}
print+Just (), another (), Perl (), Hacker ();'

Anno Siegel

unread,
Jul 19, 2005, 10:00:23 AM7/19/05
to

Well, you *can't* reuse accessors and be implementation-independent.
Rule of the game, no two ways about it.

> You will have to redefined *every* method of a parent class.

Only those methods that de-reference their object. This example
class has only one non-accessor ->total, but that's only an example.
In a real class the balance will be far more in favor of non-accessors,
especially if the class is written with this in mind.

> Take for instance the above example - since you aren't going to break
> encapsulation, you don't know how the class is implemented. It might as
> well be:
>
>
> package Parent;
>
> sub new {
> my $class = shift;
> my ( $alpha, $beta) = @_;
> bless [ $alpha, $beta, $alpha + $beta ], $class;
> }
>
> sub alpha { $_[ 0]->[ 0] }
> sub beta { $_[ 0]->[ 1] }
>
> sub total { $_[ 0]->[ 2] }
>
>
> It has the same interface, but if you now create your Client class
> as presented, calling the method 'total' results in "Not an ARRAY reference".

Same interface, but now you have made ->total is an accessor and yes,
that means it must be overridden.

> You have to redefine any method that touches an attribute directly - and
> you either have to peek inside (breaking encapsulation) to know which
> methods touch an attribute - or redefine every method.

That's why I'm preaching that accessors must be documented. An inheriting
class must know what they are and how to override them.

> But if you redefine every method, what's the point of inheritance?

That's why carelessly written classes that access their objects all over
the place are useless for inheritance. A good class defines a handful
of accessors and then never touches the object again. Then most of the
useful stuff *can* be inherited.

If the inheriting class has an object of the base class a component,
(so the is-a relation is based on a has-a relation), even accessors
can be made inheritable with a little trick the base class must provide.
I'll post a rewrite of my example a little later.

Anno

Anno Siegel

unread,
Jul 19, 2005, 1:42:49 PM7/19/05
to
Anno Siegel <anno...@lublin.zrz.tu-berlin.de> wrote in comp.lang.perl.misc:

> Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:
> > Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXXXIX
> > September MCMXCIII in <URL:news:dbhc62$53b$1...@mamenchi.zrz.TU-Berlin.DE>:
> > :) Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:
> > :) > Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXXXIX
> > :) > September MCMXCIII in <URL:news:dbfv8r$88k$1...@mamenchi.zrz.TU-Berlin.DE>:

[big snip]

> That's why carelessly written classes that access their objects all over
> the place are useless for inheritance. A good class defines a handful
> of accessors and then never touches the object again. Then most of the
> useful stuff *can* be inherited.
>
> If the inheriting class has an object of the base class a component,

^^^^^^^^^^^^^^^^^^^^^^

That should have been "...base class *as* a component", sorry.

> (so the is-a relation is based on a has-a relation), even accessors
> can be made inheritable with a little trick the base class must provide.
> I'll post a rewrite of my example a little later.

Okay, here goes.

The code for the base class is mostly unchanged. The only difference is
that it inserts a do-nothing method (one that just returns its object) into
all of its accessors (not in other methods). So if the accessor was

sub alpha { $_[ 0]->[ 0] }

it becomes

sub alpha { $_[ 0]->parent->[ 0] }
# ...
sub parent { shift }

Obviously, this doesn't change the behavior of the class, except for
wasting some time (but we're doing OO here, Efficiency is down the hall).
So clients who don't know about the change continue to function.

The no-op is called like the class (de-emphasized by lower-casing). It
could, of course, be called anything, but that is a good choice from the
clients point of view if the client chooses to use the facility.

It does that by defining a field that holds an object of class Parent
and calling the accessor to that field "parent", so it overrides that
method in the base class.

sub new {
# ...
bless {
parent => Parent->new( ...),
# ...
}, $class;
}

sub parent { $_[ 0]->{ parent} }

The effect is that the base class, when it comes to accessing an object,
interpolates the 'parent' method and sees an object of its own class which
it can handle.

This alone allows the client to inherit from Parent, that is, it can
put "Parent" on @ISA and all Parent methods will work using the parent
component. Thus it must override only one method. It can go on to
override specific other methods to modify the behavior.

So here is my original example re-written this way. The class Client_orig
is how it must be done (well, one way) without the ->parent method. It
still works with the modified Parent, but the modified Client is more
orderly.

Anno

#!/usr/local/bin/perl


use strict; use warnings; $| = 1;

use Vi::QuickFix;

my $c = Client->new( 5, 6, 7);

print "$_ -> ", $c->$_, "\n" for qw( alpha beta gamma delta total);

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

package Parent;

sub new {
my $class = shift;
my ( $alpha, $beta) = @_;

bless [ $alpha, $beta], $class;
}

sub parent { shift }

sub alpha { $_[ 0]->parent->[ 0] }
sub beta { $_[ 0]->parent->[ 1] }

sub total { $_[ 0]->alpha + $_[ 0]->beta }

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

package Client;


BEGIN { our @ISA = 'Parent' }

sub new {
my $class = shift;
my ( $alpha, $gamma, $delta) @_;
bless {
parent => Parent->new( $alpha, undef),


gamma => $gamma,
delta => $delta,

}, $class,
}

sub parent { $_[ 0]->{ parent} }


sub gamma { $_[ 0]->{ gamma} }

sub delta { $_[ 0]->{ delta} }

sub beta { $_[ 0]->gamma + $_[ 0]->delta }

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

package Client_orig;


BEGIN { our @ISA = 'Parent' }

sub new {
my $class = shift;


my ( $alpha, $gamma, $delta) = @_;
bless {
alpha => $alpha,
gamma => $gamma,
delta => $delta,

}, $class;
}

sub alpha { $_[ 0]->{ alpha} }


sub gamma { $_[ 0]->{ gamma} }

sub delta { $_[ 0]->{ delta} }

sub beta { $_[ 0]->gamma + $_[ 0]->delta }

__END__

A. Sinan Unur

unread,
Jul 19, 2005, 1:50:34 PM7/19/05
to
anno...@lublin.zrz.tu-berlin.de (Anno Siegel) wrote in
news:dbje2p$cp9$1...@mamenchi.zrz.TU-Berlin.DE:

> The code for the base class is mostly unchanged. The only difference
> is that it inserts a do-nothing method (one that just returns its
> object) into all of its accessors (not in other methods). So if the
> accessor was
>
> sub alpha { $_[ 0]->[ 0] }
>
> it becomes
>
> sub alpha { $_[ 0]->parent->[ 0] }
> # ...
> sub parent { shift }

[ rest of the discussion and code snipped ]

Anno:

I wanted to thank you very much for this series of posts, especially
this last one. I found it very informative.

Anno Siegel

unread,
Jul 19, 2005, 5:09:56 PM7/19/05
to
A. Sinan Unur <1u...@llenroc.ude.invalid> wrote in comp.lang.perl.misc:

> anno...@lublin.zrz.tu-berlin.de (Anno Siegel) wrote in
> news:dbje2p$cp9$1...@mamenchi.zrz.TU-Berlin.DE:
>
> > The code for the base class is mostly unchanged. The only difference
> > is that it inserts a do-nothing method (one that just returns its
> > object) into all of its accessors (not in other methods). So if the
> > accessor was
> >
> > sub alpha { $_[ 0]->[ 0] }
> >
> > it becomes
> >
> > sub alpha { $_[ 0]->parent->[ 0] }
> > # ...
> > sub parent { shift }
>
> [ rest of the discussion and code snipped ]
>
> Anno:
>
> I wanted to thank you very much for this series of posts, especially
> this last one. I found it very informative.

Thankyou. It's nice to be appreciated. [As Brian (Nobull) just said in
another thread.]

In fact, I think I'll make a (not much) more extensive writeup of this
material and put it on the web (at least). The final trick deserves
publicity, if I say so myself, but even without it, more awareness of
accessors and their significance would help OO programming in Perl.

Anno

Abigail

unread,
Jul 19, 2005, 7:08:04 PM7/19/05
to
Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXL
September MCMXCIII in <URL:news:dbj11n$57m$1...@mamenchi.zrz.TU-Berlin.DE>:
%%
%% That's why I'm preaching that accessors must be documented. An inheriting
%% class must know what they are and how to override them.


But that's breaking encapsulation. 'Accessor's are only a meaningful
term for the class that defines the accessor - any other class should
not have to know what is an accessor or not. With proper encapsulation,
a class, when viewed from the outside, is a black box. The box keeps
state, and it has some methods where you can poke at the box. Whether
a method happens to return an attribute or not should be irrelevant.
If you need to know, you break encapsulation.


How do you subclass a class that keeps state, but doesn't provide
an accessor?

package Angry::Snake;

sub new {
bless \do {my $c = int rand 5} => shift;
}

sub poke_it_with_a_stick {
my $snake = shift;
$snake -> attack if $$snake -- < 0;
}

sub attack { ... }


Abigail
--
map{${+chr}=chr}map{$_=>$_^ord$"}$=+$]..3*$=/2;
print "$J$u$s$t $a$n$o$t$h$e$r $P$e$r$l $H$a$c$k$e$r\n";

Anno Siegel

unread,
Jul 20, 2005, 5:38:05 AM7/20/05
to
Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:
> Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXL
> September MCMXCIII in <URL:news:dbj11n$57m$1...@mamenchi.zrz.TU-Berlin.DE>:
> %%
> %% That's why I'm preaching that accessors must be documented. An inheriting
> %% class must know what they are and how to override them.
>
>
> But that's breaking encapsulation. 'Accessor's are only a meaningful
> term for the class that defines the accessor - any other class should
> not have to know what is an accessor or not. With proper encapsulation,
> a class, when viewed from the outside, is a black box. The box keeps
> state, and it has some methods where you can poke at the box. Whether
> a method happens to return an attribute or not should be irrelevant.
> If you need to know, you break encapsulation.

True. The fundamental breach in encapsulation is that Perl objects
have a life of their own, they aren't opaque structures (nothing but
objects) like in most OO languages. That flaw can't be removed by
argumentation and paradigm shifts, it's here to stay.

The distinction in accessors and non-accessors can help in making
that breach manageable, not make it go away.

By publishing which methods are accessors and which aren't, you are
making a considerable implementational commitment. In particular,
you can't make an accessor out of what used not to be one. Your
client's code would break.

> How do you subclass a class that keeps state, but doesn't provide
> an accessor?
>
> package Angry::Snake;
>
> sub new {
> bless \do {my $c = int rand 5} => shift;
> }
>
> sub poke_it_with_a_stick {
> my $snake = shift;
> $snake -> attack if $$snake -- < 0;
> }
>
> sub attack { ... }

Mmmmm, nice snakey, pretty snakey, I'm not poking, okay...?

No, you can't inherit ->poke_with_a_stick. That's because it's an
accessor, even if it is not a field accessor in the usual sense.
It accesses (de-references) the object, and so it's out.

If Angry::Snake were written with an overridable method (->snake)
guarding the access, like this:

sub poke_it_with_a_stick {
my $snake = shift;

$snake -> attack if ${ $snake->snake} -- < 0;
}

sub snake { shift }

things would be different. Here's a less aggressive snake that doesn't
always notice when it is poked:

package Sleepy::Snake;
BEGIN { our @ISA = 'Angry::Snake' }

sub new {
bless {
sleepiness => 0.5,
snake => Angry::Snake->new,
}, shift;
}

sub snake { $_[ 0]->{ snake} }

sub poke_it_with_a_stick {
my $sn = shift;
$sn->SUPER::poke_it_with_a_stick if rand > $sn->sleepiness;
}

sub sleepiness {
$_[ 0]->{ sleepiness} = shift if @_ > 1;
$_[ 0]->{ sleepiness};

Anno Siegel

unread,
Jul 20, 2005, 6:41:47 AM7/20/05
to
[this article supercedes an earlier version to correct a coding error]

Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:

> Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXL
> September MCMXCIII in <URL:news:dbj11n$57m$1...@mamenchi.zrz.TU-Berlin.DE>:
> %%
> %% That's why I'm preaching that accessors must be documented. An inheriting
> %% class must know what they are and how to override them.
>
>
> But that's breaking encapsulation. 'Accessor's are only a meaningful
> term for the class that defines the accessor - any other class should
> not have to know what is an accessor or not. With proper encapsulation,
> a class, when viewed from the outside, is a black box. The box keeps
> state, and it has some methods where you can poke at the box. Whether
> a method happens to return an attribute or not should be irrelevant.
> If you need to know, you break encapsulation.

True. The fundamental breach in encapsulation is that Perl objects


have a life of their own, they aren't opaque structures (nothing but
objects) like in most OO languages. That flaw can't be removed by
argumentation and paradigm shifts, it's here to stay.

The distinction in accessors and non-accessors can help in making
that breach manageable, not make it go away.

By publishing which methods are accessors and which aren't, you are
making a considerable implementational commitment. In particular,
you can't make an accessor out of what used not to be one. Your
client's code would break.

> How do you subclass a class that keeps state, but doesn't provide


> an accessor?
>
> package Angry::Snake;
>
> sub new {
> bless \do {my $c = int rand 5} => shift;
> }
>
> sub poke_it_with_a_stick {
> my $snake = shift;
> $snake -> attack if $$snake -- < 0;
> }
>
> sub attack { ... }

Mmmmm, nice snakey, pretty snakey, I'm not poking, okay...?

No, you can't inherit ->poke_with_a_stick. That's because it's an
accessor, even if it is not a field accessor in the usual sense.
It accesses (de-references) the object, and so it's out.

If Angry::Snake were written with an overridable method (->snake)
guarding the access, like this:

sub poke_it_with_a_stick {
my $snake = shift;


$snake -> attack if ${ $snake->snake} -- < 0;
}

sub snake { shift }

things would be different. Here's a less aggressive snake that doesn't
always notice when it is poked:

package Sleepy::Snake;
BEGIN { our @ISA = 'Angry::Snake' }

sub new {


bless {
sleepiness => 0.5,
snake => Angry::Snake->new,
}, shift;
}

sub snake { $_[ 0]->{ snake} }

sub poke_it_with_a_stick {
my $sn = shift;
$sn->SUPER::poke_it_with_a_stick if rand > $sn->sleepiness;
}

sub sleepiness {

# $_[ 0]->{ sleepiness} = shift if @_ > 1; # this is in error
$_[ 0]->{ sleepiness} = $_[ 1] if @_ > 1;
$_[ 0]->{ sleepiness};
}

Anno

Abigail

unread,
Jul 22, 2005, 6:35:38 PM7/22/05
to
Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXLI
September MCMXCIII in <URL:news:dbl9pb$g3r$2...@mamenchi.zrz.TU-Berlin.DE>:

> [[ Snipped for brevity ]]


Here's how I would subclass Angry::Snake. Note that I subclass the
original Angry::Snake, without requiring it to have an "accessor".


package Angry::Snake;

sub new {
bless \do {my $c = int rand 5} => shift;
}

sub poke_it_with_a_stick {
my $snake = shift;
$snake -> attack if $$snake -- < 0;
}

sub attack { ... }

package Sleepy::Snake; {
use Scalar::Util qw 'refaddr';

our @ISA = qw /Angry::Snake/;

my %sleepiness; # Store the attribute in a lexical variable.

sub set_sleepiness {
my $snake = shift;
$sleepiness {refaddr $snake} = shift;
$snake;
}
sub sleepiness {
my $snake = shift;
$sleepiness {refaddr $snake};


}

sub poke_it_with_a_stick {
my $snake = shift;

$snake -> SUPER::poke_it_with_a_stick
if rand > $snake -> sleepiness;
}

sub DESTROY {
my $snake = shift;
delete $sleepiness {refaddr $snake};
}
}

package main;

my $snake = Sleepy::Snake -> new -> set_sleepiness (0.5);


Note that Sleepy::Snake doesn't have its own constructor. Nor does it rely
on how Angry::Snake has been implemented in any way. It doesn't require
its super class to make accessors available. It doesn't force anything
on a potential subclass either.


Abigail
--
perl -wlne '}print$.;{' file # Count the number of lines.

Eric Schwartz

unread,
Jul 22, 2005, 7:53:32 PM7/22/05
to
Abigail <abi...@abigail.nl> writes:
> Here's how I would subclass Angry::Snake. Note that I subclass the
> original Angry::Snake, without requiring it to have an "accessor".
>
> package Angry::Snake;
>
> sub new {
> bless \do {my $c = int rand 5} => shift;
> }
>
> sub poke_it_with_a_stick {
> my $snake = shift;
> $snake -> attack if $$snake -- < 0;
> }
>
> sub attack { ... }

<snip rest of example>

Ow. Stop hurting my brain like that. So assuming you wanted to store
multiple bits of data, would Sick::Snake look something like:

package Sick::Snake


use Scalar::Util qw 'refaddr';

our @ISA = qw/Angry::Snake/;

my %attr;

sub set_shivering {
my $snake = shift;
$attr{refaddr $snake}{shivering} = shift;
$snake;
}

sub set_sneezing {
my $snake = shift;
$attr{refaddr $snake}{sneezing} = shift;
$snake;
}

sub shivering {...}
sub sneezing {...}

and so on?

That's a very neat trick. Should I ever be forced to write OO in
Perl, I will try to keep that in mind. Also, nice plug for
Scalar::Util, which while not quite as nifty as List::Util, is still
one of the more underappreciated modules in Perl, I think.

-=Eric

Abigail

unread,
Jul 22, 2005, 8:21:40 PM7/22/05
to
Eric Schwartz (emsc...@pobox.com) wrote on MMMMCCCXLIII September
MCMXCIII in <URL:news:etoy87y...@wilson.emschwar>:
== Abigail <abi...@abigail.nl> writes:
== > Here's how I would subclass Angry::Snake. Note that I subclass the
== > original Angry::Snake, without requiring it to have an "accessor".
== >
== > package Angry::Snake;
== >
== > sub new {
== > bless \do {my $c = int rand 5} => shift;
== > }
== >
== > sub poke_it_with_a_stick {
== > my $snake = shift;
== > $snake -> attack if $$snake -- < 0;
== > }
== >
== > sub attack { ... }
==
== <snip rest of example>
==
== Ow. Stop hurting my brain like that. So assuming you wanted to store
== multiple bits of data, would Sick::Snake look something like:
==
== package Sick::Snake
== use Scalar::Util qw 'refaddr';
==
== our @ISA = qw/Angry::Snake/;
==
== my %attr;
==
== sub set_shivering {
== my $snake = shift;
== $attr{refaddr $snake}{shivering} = shift;
== $snake;
== }
==
== sub set_sneezing {
== my $snake = shift;
== $attr{refaddr $snake}{sneezing} = shift;
== $snake;
== }
==
== sub shivering {...}
== sub sneezing {...}


That's one way, but I don't like that (too much typing, and I prefer
to avoid using literal strings for hash keys - using lexical variables
gives you all the power 'use strict' can give you). I do it this way:

package Sick::Snake; {

use Scalar::Util qw 'refaddr';
our @ISA = qw /Angry::Snake/;

my %shivering;
my %sneezing;

sub DESTROY {
my $snake = shift;

delete $shivering {refaddr $snake};
delete $sneezing {refaddr $snake};
}

sub set_shivering {
my $snake = shift;

$shivering {refaddr $snake} = shift;
$snake;
}
sub shivering {
my $snake = shift;
$shivering {refaddr $snake}
}

sub set_sneezing {
my $snake = shift;

$sneezing {refaddr $snake} = shift;
$snake;
}
sub sneezing {
my $snake = shift;
$sneezing {refaddr $snake}
}
}


== That's a very neat trick. Should I ever be forced to write OO in
== Perl, I will try to keep that in mind. Also, nice plug for
== Scalar::Util, which while not quite as nifty as List::Util, is still
== one of the more underappreciated modules in Perl, I think.


I've called this technique 'Inside Out Objects'. Damian Conway promotes
this style in his new book, "Perl Best Practices". He has also written
a module, Class::Std, that takes care of some of the work.

Eric Schwartz

unread,
Jul 22, 2005, 8:47:25 PM7/22/05
to
Abigail <abi...@abigail.nl> writes:
> That's one way, but I don't like that (too much typing, and I prefer
> to avoid using literal strings for hash keys - using lexical variables
> gives you all the power 'use strict' can give you). I do it this way:
>
> package Sick::Snake; {
>
> use Scalar::Util qw 'refaddr';
> our @ISA = qw /Angry::Snake/;
>
> my %shivering;
> my %sneezing;

I suppose the only concern I had was that if you have a number of
attributes for an object, this list might become wearying itself to
type. But then, I suppose you only have to do so once, and anyhow, a
nice comment block to alert the reader that these were attributes
would work fine. It just reminds me of a project I once worked on
where there was a data structure with literally dozens of parallel
arrays (poorly designed, I'll concede), and it was often hard to track
modifications so that they tracked each of these.

> sub DESTROY {
> my $snake = shift;
> delete $shivering {refaddr $snake};
> delete $sneezing {refaddr $snake};
> }

Here in particular, if you aren't careful, you might add an attribute
and forget to put it in DESTROY, whereas my approach would look like:

sub DESTROY {
my $snake = shift;

delete $attrs{refaddr $snake};
}

But your arguments for lexicals giving the equivalent of use strict is
a strong one, and I don't suppose it's an undue burden to remember to
add a new attribute to DESTROY. Anyhow, even if you forget, the worst
that would happen is you hold a reference that is inaccessible-- a
memory leak, but not a critical program failure in itself.

-=Eric

Abigail

unread,
Jul 22, 2005, 9:16:54 PM7/22/05
to
Eric Schwartz (emsc...@pobox.com) wrote on MMMMCCCXLIV September
MCMXCIII in <URL:news:etomzoe...@wilson.emschwar>:

"" Abigail <abi...@abigail.nl> writes:
"" > That's one way, but I don't like that (too much typing, and I prefer
"" > to avoid using literal strings for hash keys - using lexical variables
"" > gives you all the power 'use strict' can give you). I do it this way:
"" >
"" > package Sick::Snake; {
"" >
"" > use Scalar::Util qw 'refaddr';
"" > our @ISA = qw /Angry::Snake/;
"" >
"" > my %shivering;
"" > my %sneezing;
""
"" I suppose the only concern I had was that if you have a number of
"" attributes for an object, this list might become wearying itself to
"" type. But then, I suppose you only have to do so once, and anyhow, a
"" nice comment block to alert the reader that these were attributes
"" would work fine. It just reminds me of a project I once worked on
"" where there was a data structure with literally dozens of parallel
"" arrays (poorly designed, I'll concede), and it was often hard to track
"" modifications so that they tracked each of these.
""
"" > sub DESTROY {
"" > my $snake = shift;
"" > delete $shivering {refaddr $snake};
"" > delete $sneezing {refaddr $snake};
"" > }
""
"" Here in particular, if you aren't careful, you might add an attribute
"" and forget to put it in DESTROY, whereas my approach would look like:

If you are afraid you forget it, either use Class::Std (and then you
won't even have to create a DESTROY function), or do something like:

my @attrs = \my (%shivering, %sneezing, ...);

sub DESTROY {
my $snake = shift;

delete $$_ {refaddr $snake} for @attr;
}

"" sub DESTROY {
"" my $snake = shift;
"" delete $attrs{refaddr $snake};
"" }
""
"" But your arguments for lexicals giving the equivalent of use strict is
"" a strong one, and I don't suppose it's an undue burden to remember to
"" add a new attribute to DESTROY. Anyhow, even if you forget, the worst
"" that would happen is you hold a reference that is inaccessible-- a
"" memory leak, but not a critical program failure in itself.


No, the memory leak isn't the worst problem. That's indeed a minor problem.
Not cleaning up attributes has the potential for a program failure though.
Inside-Out object work because every the memory address of every reference
is unique - but the addresses are only unique for the currently existing
references. If a reference goes out of scope (or rather, the thing it
points to), the memory may be reused, and a new reference might have the
same address as an old one. If you don't clean up your attributes, new
objects may inherit attributes from old, retired, objects.

Abigail
--
perl -e '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %;
BEGIN {% % = ($ _ = " " => print "Just Another Perl Hacker\n")}'

Anno Siegel

unread,
Jul 23, 2005, 2:52:16 PM7/23/05
to
Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:
> Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXLI
> September MCMXCIII in <URL:news:dbl9pb$g3r$2...@mamenchi.zrz.TU-Berlin.DE>:
>
> > [[ Snipped for brevity ]]
>
>
> Here's how I would subclass Angry::Snake. Note that I subclass the
> original Angry::Snake, without requiring it to have an "accessor".

Ah, but in my book (that would be a little paper I'm writing about
inheritance in Perl) it *has* an accessor. Any method that accesses the
object by de-referencing the object is an accessor, whether it returns
the value to the caller or does something else with it. That would make
->poke_it_with_a_stick an accessor. A field accessor in the usual
sense is just a special case. In most mainstream OO languages there
are no accessors except field accessors, so the two notions coincide,
but Perl is different.

That's just terminology. Maybe I should think it over and find a better
term. But what can you call a method whose distinguishing property is that
it accesses the object?

No, it can't. One of the tenets about Perl inheritance is "If you
inherit an accessor, you must also inherit ->new", which is what happens
here. Inherit as opposed to override.

Like all short formulas about complex fields (except exp(i*pi) = -1, hehe),
it is wrong. You can override ->new, provided you call the base class'
->new to create the object. Your objects must be structurally the same
as those of the base class if you want the base class accessors to work
on them. Put like that it's a truism.

However, in package Sleepy::Snake it would be safe to override ->new

sub new { shift()->SUPER::new->set_sleepiness( 0.5) }

so as not to create snakes with undefined sleepiness.

> Nor does it rely
> on how Angry::Snake has been implemented in any way. It doesn't require
> its super class to make accessors available. It doesn't force anything
> on a potential subclass either.

Quite so, it carries itself the full weight of inheriting from the
deliberately inheritance-unfriendly Angry::Snake. The weight is the
somewhat unusual implementation. It shows again that inheritance in
Perl doesn't come for free. Someone must support it, the base class
and/or the inheriting class.

So "Inside-out" is what you call them. (I've read some more of the thread,
but wanted to reply with your code in sight.) It's an ingenious answer
to the question: How can I assign additional data (fields) to an object when
I'm not allowed to change its structure?

I suppose you are using Scalar::Util::refaddr because stringification
may be overloaded for the base class. Otherwise the stringified object
would serve as well. I have used overload::StrVal for the purpose.
On re-reading perldoc overload I see that there is now a pointer to
Scalar::Util::refaddr.

Just out of spite, below is yet another way to inherit poke_it_with-
_a_stick from an (unchanged) Angry::Snake. It uses de-reference
overloading to persuade the base class to access Sleepy::Snake objects
in a special way. Overloading every possible kind of de-reference makes
sure it continues to work when Angry::Snake changes its implementation.
It is more heavy handed than the elegant inside-out objects, and it inhibits
further inheritance in a major way. Overloading de-reference is bad for
inheritance, carpet-bombing it over all types, as I do here, is worse.
The merit of this way, if any, is the standard implementation of
Sleepy::Snake as a typical hash-as-a-struct.

package Sleepy::Snake;
use base 'Angry::Snake';
use overload map { $_ => 'snake' } qw( ${} @{} %{} &{} *{});

sub new {
my $class = shift;

bless {
sleepiness => 0.5,
snake => Angry::Snake->SUPER::new,
}, $class;
}

sub set_sleepiness { $_[ 0]->{ sleepiness} = $_[ 1]; shift }


sub sleepiness { $_[ 0]->{ sleepiness} }

# we're the ->{ snake} field for Angry::Snake, ourselves for
# everyone else
sub snake { caller eq 'Angry::Snake' ? $_[ 0]->{ snake} : $_[ 0] }

sub poke_it_with_a_stick {
my $snake = shift;
$snake -> SUPER::poke_it_with_a_stick if rand > $snake -> sleepiness;
}

__END__

Abigail

unread,
Jul 23, 2005, 4:25:21 PM7/23/05
to
Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXLIV
September MCMXCIII in <URL:news:dbu3l0$nf3$1...@mamenchi.zrz.TU-Berlin.DE>:
{} Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:

{} > Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXLI
{} > September MCMXCIII in <URL:news:dbl9pb$g3r$2...@mamenchi.zrz.TU-Berlin.DE>:
{} >
{} > > [[ Snipped for brevity ]]
{} >
{} >
{} > Here's how I would subclass Angry::Snake. Note that I subclass the
{} > original Angry::Snake, without requiring it to have an "accessor".
{}
{} Ah, but in my book (that would be a little paper I'm writing about
{} inheritance in Perl) it *has* an accessor. Any method that accesses the
{} object by de-referencing the object is an accessor, whether it returns
{} the value to the caller or does something else with it. That would make
{} ->poke_it_with_a_stick an accessor. A field accessor in the usual
{} sense is just a special case. In most mainstream OO languages there
{} are no accessors except field accessors, so the two notions coincide,
{} but Perl is different.

Oh, it has an accessor allright. Whether or not the super class has
an accessor is not important. Or rather, it's irrelevant. And that's
(IMO) the beauty of Inside-Out Objects. It's _irrelevant_ whether the
superclass has accessors. Or attributes/fields. Or how it stores them.
How the superclass is implemented does not matter - all that matters
is its API. And the whole implementation can change, accessors can turn
into non-accessors, or visa versa, if the API remains the same, there's
no need to update the inheriting class.

{} That's just terminology. Maybe I should think it over and find a better


{} term. But what can you call a method whose distinguishing property is that
{} it accesses the object?

I don't really care how you call them. I don't think a different term from
them is important. In fact, when I call methods in a class, I do not want
to have to know whether it's an accessor or not. When I look to a class
from anywhere but the class itself, all I should see is methods. If I
need to know (perhaps to do something different) that a method is an
"accessor", something is wrong. IMO, it breaks encapsulation, and OO with
broken encapsulation is no fun at all.

{} > Note that Sleepy::Snake doesn't have its own constructor.


{}
{} No, it can't. One of the tenets about Perl inheritance is "If you
{} inherit an accessor, you must also inherit ->new", which is what happens
{} here. Inherit as opposed to override.

Sure it can have its own constructor. I just decided not to. I prefer
not to configure an object (that is, setting attribute values) in a
constructor because that makes multiple inheritance a real pain in the
ass, so I prefer to only have constructors in classes that don't inherit
other classes, and such constructors should only return the blessed
reference, and do not anything else. Having said, if I were to create
a constructor for the Sleepy::Snake class, I'd do it like this:

sub new {
my $snake = Angry::Snake -> new; # Let the class set itself up
# in whatever way it pleases.
$sleepiness {refaddr $snake} = 0.5; # Default value.
bless $snake => shift; # Bless it to our class.
}

{} Like all short formulas about complex fields (except exp(i*pi) = -1, hehe),


{} it is wrong. You can override ->new, provided you call the base class'
{} ->new to create the object. Your objects must be structurally the same
{} as those of the base class if you want the base class accessors to work
{} on them. Put like that it's a truism.

Yes. But that's the beauty of Inside-Out Objects. It doesn't care what
structure the super class has, because it doesn't use the structure at
all. All it needs is the memory address.

{} However, in package Sleepy::Snake it would be safe to override ->new


{}
{} sub new { shift()->SUPER::new->set_sleepiness( 0.5) }
{}
{} so as not to create snakes with undefined sleepiness.

That works as well as the constructor I used above. But it makes
multiple inheritance a lot harder.

{} > Nor does it rely

{} > on how Angry::Snake has been implemented in any way. It doesn't require
{} > its super class to make accessors available. It doesn't force anything
{} > on a potential subclass either.
{}
{} Quite so, it carries itself the full weight of inheriting from the
{} deliberately inheritance-unfriendly Angry::Snake. The weight is the
{} somewhat unusual implementation. It shows again that inheritance in
{} Perl doesn't come for free. Someone must support it, the base class
{} and/or the inheriting class.
{}
{} So "Inside-out" is what you call them. (I've read some more of the thread,
{} but wanted to reply with your code in sight.) It's an ingenious answer
{} to the question: How can I assign additional data (fields) to an object when
{} I'm not allowed to change its structure?

It solves two of the three problems I have traditional (hash based) objects
in Perl:

* No encapsulation.
* No 'use strict' benefits when accessing object attributes.

But those are the two biggest problems.

\begin{side-remark}
My third problem is that getting to object attributes takes too much typing.
For instance, in a non-OO world, adding elements to an array is written as
follows:

push @array => 'one', 'two', 'three';

Quite straight forward. But in OO, we have something like:

push @{$_ [0] -> {array}} => 'one', 'two', 'three'; # Or
push @{${$_ [0]} {array}} => 'one', 'two', 'three';

Even with Inside-Out Objects, we have:

push @{$array {refaddr $_ [0]}} => 'one', 'two', 'three';

But I've fixed that as well. With Lexical::Attributes, I just write:

push @.array => 'one', 'two', 'three';

But that's for a different thread.
\end{side-remark}

{} I suppose you are using Scalar::Util::refaddr because stringification


{} may be overloaded for the base class. Otherwise the stringified object
{} would serve as well. I have used overload::StrVal for the purpose.
{} On re-reading perldoc overload I see that there is now a pointer to
{} Scalar::Util::refaddr.

Indeed, overloading stringification is a problem. Reblessing to a
different class is a problem as well if you use the stringified form of
the object to index. A minor benefit is that C<refaddr $obj> is shorter
string than C<"$obj">, so storage of keys should be somewhat less,
and the calculation of the hash value should take a fraction less.

{} Just out of spite, below is yet another way to inherit poke_it_with-


{} _a_stick from an (unchanged) Angry::Snake.

;-)


Abigail
--
perl -e '$a = q 94a75737420616e6f74686572205065726c204861636b65720a9 and
${qq$\x5F$} = q 97265646f9 and s g..g;
qq e\x63\x68\x72\x20\x30\x78$&eggee;
{eval if $a =~ s e..eqq qprint chr 0x$& and \x71\x20\x71\x71qeexcess}'

Anno Siegel

unread,
Jul 24, 2005, 2:41:54 PM7/24/05
to

Well, paradise. A sunlit Caribbean island with no inheritance tax. The
one thing I don't see at a glance is how you would do multiple inheritance
that way. Your object *is* an object of the base class, only blessed
into yours. It can't be physically be many structures at once.

> {} That's just terminology. Maybe I should think it over and find a better
> {} term. But what can you call a method whose distinguishing property is that
> {} it accesses the object?
>
> I don't really care how you call them. I don't think a different term from
> them is important. In fact, when I call methods in a class, I do not want
> to have to know whether it's an accessor or not. When I look to a class
> from anywhere but the class itself, all I should see is methods. If I
> need to know (perhaps to do something different) that a method is an
> "accessor", something is wrong. IMO, it breaks encapsulation, and OO with
> broken encapsulation is no fun at all.

I agree. In inheritance paradise there is no need for the term "accessor".
But that blissful state is not where programmers find themselves who
go about Perl OO naively, or follow what they are taught in most tutorials.

To see why and how things go wrong, and what to do about it, I think I
need the term. But that's no concern of yours, you're right to point that
out.

As mentioned above, that was my first concern about your approach. How
do you inherit from more than one class in this way? Could you elaborate?

[some snippage]

> Even with Inside-Out Objects, we have:
>
> push @{$array {refaddr $_ [0]}} => 'one', 'two', 'three';
>
> But I've fixed that as well. With Lexical::Attributes, I just write:
>
> push @.array => 'one', 'two', 'three';
>
> But that's for a different thread.
> \end{side-remark}

Huh, what's that? A source filter? Oh, never mind. I'll look if I must
know.

I find this thread very worthwhile.

Abigail

unread,
Jul 25, 2005, 6:04:36 PM7/25/05
to
Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXLV
September MCMXCIII in <URL:news:dc0ndi$7pg$1...@mamenchi.zrz.TU-Berlin.DE>:

[ Inside-Out Objects ]

{}
{} Well, paradise. A sunlit Caribbean island with no inheritance tax. The


{} one thing I don't see at a glance is how you would do multiple inheritance
{} that way. Your object *is* an object of the base class, only blessed
{} into yours. It can't be physically be many structures at once.


If you're inheriting from two classes who use a different structure,
it's going to be hard. With different structures, you'll have to resort
to a has-a relationship, and dispatch all the methods of said class.

If you are inheriting from two classes that use the same structure, you
might be lucky, and will be able to do something by breaking encapsulation
and merging the objects. If both classes use refs to hashes, and they don't
use the same attributes, you can fill on hash with the content of the other.
Or you use a has-a relationship.

If the classes you want to inherit from are Inside-Out Objects, and their
constructors only construct (and don't initialize) the object, multiple
inheritance is easy:

#!/usr/bin/perl

use strict;
use warnings;
no warnings qw /syntax/;


package Floor::Wax; {
use Scalar::Util 'refaddr';

my %colour;

sub DESTROY {
my $self = shift;
delete $colour {refaddr $self};
}

sub new {bless \do {my $v} => shift;}

sub init {
my $self = shift;
$colour {refaddr $self} = "yellow";
$self;
}

sub colour {
my $self = shift;
$colour {refaddr $self};
}
}

package Dessert::Topping; {
use Scalar::Util 'refaddr';

my %colour;

sub DESTROY {
my $self = shift;
delete $colour {refaddr $self};
}

sub new {bless \do {my $v} => shift;}

sub init {
my $self = shift;
$colour {refaddr $self} = "white";
$self;
}

sub colour {
my $self = shift;
$colour {refaddr $self};
}
}

package Perl; {
our @ISA = qw /Floor::Wax Dessert::Topping/;

sub init {
my $self = shift;
$self -> Floor::Wax::init;
$self -> Dessert::Topping::init;
}

sub colour {
my $self = shift;

sprintf "%s and %s" => $self -> Floor::Wax::colour,
$self -> Dessert::Topping::colour;
}
}

package main;

my $p = Perl -> new -> init;

print $p -> colour, "\n";


__END__
yellow and white

Abigail
--
# Count the number of lines; code doesn't match \w. Linux specific.
()=<>;$!=$=;($:,$,,$;,$")=$!=~/.(.)..(.)(.)..(.)/;
$;++;$*++;$;++;$*++;$;++;`$:$,$;$" $. >&$*`;

Anno Siegel

unread,
Jul 26, 2005, 2:34:45 PM7/26/05
to
Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:
> Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXLV
> September MCMXCIII in <URL:news:dc0ndi$7pg$1...@mamenchi.zrz.TU-Berlin.DE>:
>
> [ Inside-Out Objects ]
>
> {}
> {} Well, paradise. A sunlit Caribbean island with no inheritance tax. The
> {} one thing I don't see at a glance is how you would do multiple inheritance
> {} that way. Your object *is* an object of the base class, only blessed
> {} into yours. It can't be physically be many structures at once.
>
>
> If you're inheriting from two classes who use a different structure,
> it's going to be hard. With different structures, you'll have to resort
> to a has-a relationship, and dispatch all the methods of said class.

Right. Base it on a has-a. The crux is how to do the dispatching.

> If you are inheriting from two classes that use the same structure, you
> might be lucky, and will be able to do something by breaking encapsulation
> and merging the objects. If both classes use refs to hashes, and they don't
> use the same attributes, you can fill on hash with the content of the other.

Okay, same old same old. Except it is now two prospective base classes
that are coupled too close for comfort, not subclass and base class.
Not sure if that's generally better, but it's an alternative, and as
such yields some leeway in design.

> Or you use a has-a relationship.

Again. Often, that's the cleanest solution. You have to support all
methods of the base class one way or another, so why not take an original
on board and support them through that.

> If the classes you want to inherit from are Inside-Out Objects, and their
> constructors only construct (and don't initialize) the object, multiple
> inheritance is easy:

[snip code that leads to]

> package Perl; {
> our @ISA = qw /Floor::Wax Dessert::Topping/;
>
> sub init {
> my $self = shift;
> $self -> Floor::Wax::init;
> $self -> Dessert::Topping::init;
> }
>
> sub colour {
> my $self = shift;
>
> sprintf "%s and %s" => $self -> Floor::Wax::colour,
> $self -> Dessert::Topping::colour;
> }
> }
>
> package main;
>
> my $p = Perl -> new -> init;
>
> print $p -> colour, "\n";
>
>
> __END__
> yellow and white

That's a very pretty bit of machinery. I'll use it to study the
significance of keeping construction and initialization apart, thanks
for the example.

So "Perl" inherits whichever ->new happens to be first on @ISA, it doesn't
matter because they're all equivalent. And if another class (not
necessarily inside-out) also had separate construction and initialization,
it should be easy to thread it into the scheme. Correct me if I'm wrong,
but it looks like an inside-out class could inherit from such a base class
of *any* type without any further measures.

Of course, few real-world classes are like that.

Abigail

unread,
Jul 26, 2005, 3:21:21 PM7/26/05
to
Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXLVII
September MCMXCIII in <URL:news:dc5vo5$iuc$1...@mamenchi.zrz.TU-Berlin.DE>:
^^
^^ So "Perl" inherits whichever ->new happens to be first on @ISA, it doesn't
^^ matter because they're all equivalent. And if another class (not
^^ necessarily inside-out) also had separate construction and initialization,
^^ it should be easy to thread it into the scheme. Correct me if I'm wrong,
^^ but it looks like an inside-out class could inherit from such a base class
^^ of *any* type without any further measures.


Indeed. By design. ;-)


Abigail
--
perl -we '$_ = q ;4a75737420616e6f74686572205065726c204861636b65720as;;
for (s;s;s;s;s;s;s;s;s;s;s;s)
{s;(..)s?;qq qprint chr 0x$1 and \161 ssq;excess;}'

Anno Siegel

unread,
Jul 27, 2005, 6:00:06 PM7/27/05
to
Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:
> Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXLVII
> September MCMXCIII in <URL:news:dc5vo5$iuc$1...@mamenchi.zrz.TU-Berlin.DE>:
> ^^
> ^^ So "Perl" inherits whichever ->new happens to be first on @ISA, it doesn't
> ^^ matter because they're all equivalent. And if another class (not
> ^^ necessarily inside-out) also had separate construction and initialization,
> ^^ it should be easy to thread it into the scheme. Correct me if I'm wrong,
> ^^ but it looks like an inside-out class could inherit from such a base class
> ^^ of *any* type without any further measures.
>
>
> Indeed. By design. ;-)

Only once, sadly. So you can inherit from as many inside-out classes as
is good for you, plus one "normal" (type-committed) class.

One could wax philosophical about inside-out objects, how a normal inside-
in object holds everything of interest inside and nothing on the outside,
and thus, turning it inside-out, the core of an inside-out object becomes
an object-shaped void which is the former empty outside of the original,
and how this void can be filled with a normally functioning object
while the inside-out object continues to function because its function
is located on the outside, but
I won't.

Instead, let me add a thought that is only loosely related. It seems
to me that inheritance and encapsulation don't go together (anywhere,
not only in Perl) in one respect. When it comes to overriding some
of the original methods, you must know how the methods in the base class
use (call) each other in order to predict the result. On the other hand,
that's an implementation detail that shouldn't concern the inheriting
class. I don't see how that can be resolved.

Anno Siegel

unread,
Jul 27, 2005, 6:02:24 PM7/27/05
to
Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:
> Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXLVII
> September MCMXCIII in <URL:news:dc5vo5$iuc$1...@mamenchi.zrz.TU-Berlin.DE>:
> ^^
> ^^ So "Perl" inherits whichever ->new happens to be first on @ISA, it doesn't
> ^^ matter because they're all equivalent. And if another class (not
> ^^ necessarily inside-out) also had separate construction and initialization,
> ^^ it should be easy to thread it into the scheme. Correct me if I'm wrong,
> ^^ but it looks like an inside-out class could inherit from such a base class
> ^^ of *any* type without any further measures.
>
>
> Indeed. By design. ;-)

Only once, sadly. So you can inherit from as many inside-out classes as


is good for you, plus one "normal" (type-committed) class.

One could wax philosophical about inside-out objects, how a normal inside-
in object holds everything of interest inside and nothing on the outside,
and thus, turning it inside-out, the core of an inside-out object becomes
an object-shaped void which is the former empty outside of the original,
and how this void can be filled with a normally functioning object
while the inside-out object continues to function because its function
is located on the outside, but I won't.

Instead, let me add a thought that is only loosely related. It seems
to me that inheritance and encapsulation don't go together (anywhere,
not only in Perl) in one respect. When it comes to overriding some
of the original methods, you must know how the methods in the base class
use (call) each other in order to predict the result. On the other hand,
that's an implementation detail that shouldn't concern the inheriting
class. I don't see how that can be resolved.

Anno

Abigail

unread,
Jul 27, 2005, 6:32:36 PM7/27/05
to
Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXLVIII
September MCMXCIII in <URL:news:dc909g$gc2$2...@mamenchi.zrz.TU-Berlin.DE>:
() Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:
() > Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXLVII
() > September MCMXCIII in <URL:news:dc5vo5$iuc$1...@mamenchi.zrz.TU-Berlin.DE>:
() > ^^
() > ^^ So "Perl" inherits whichever ->new happens to be first on @ISA, it does
() > ^^ matter because they're all equivalent. And if another class (not
() > ^^ necessarily inside-out) also had separate construction and initializati
() > ^^ it should be easy to thread it into the scheme. Correct me if I'm wron
() > ^^ but it looks like an inside-out class could inherit from such a base cl
() > ^^ of *any* type without any further measures.
() >
() >
() > Indeed. By design. ;-)
()
() Only once, sadly. So you can inherit from as many inside-out classes as
() is good for you, plus one "normal" (type-committed) class.

Unless you create some kind of has-a relationship. But this 'defect'
isn't restricted to inside-out objects. Whatever you do, it's going to
be hard to merge 2 hashes and 3 arrays. (Merging a single hash and a
single array would still be possible by overloading the object to have
@{} and %{} magic).

But in practise, the wide-spread practise (sic) of configuring an object
in the constructor makes it already impossible to do MI without falling
back on a has-a relationship.


() One could wax philosophical about inside-out objects, how a normal inside-
() in object holds everything of interest inside and nothing on the outside,
() and thus, turning it inside-out, the core of an inside-out object becomes
() an object-shaped void which is the former empty outside of the original,
() and how this void can be filled with a normally functioning object
() while the inside-out object continues to function because its function
() is located on the outside, but I won't.
()
() Instead, let me add a thought that is only loosely related. It seems
() to me that inheritance and encapsulation don't go together (anywhere,
() not only in Perl) in one respect. When it comes to overriding some
() of the original methods, you must know how the methods in the base class
() use (call) each other in order to predict the result. On the other hand,
() that's an implementation detail that shouldn't concern the inheriting
() class. I don't see how that can be resolved.


Well, IMO, it's a bad idea to override a proper subset of related methods.
A lot of inheritance is done without overriding any methods - they are
merely adding functionality, not overriding any. Then you don't have
the problem you describe above. Furthermore, a lot of overriding is done
while still calling the overridden method using SUPER.

But if you have a statistical object with two methods, 'add' to add a
new number to the set, and 'average' to return the average of the set,
overriding either of 'add' or 'average', without calling SUPER:: is
unlikely to work properly.

Abigail
--
perl -wle 'print "Prime" if (0 x shift) !~ m 0^\0?$|^(\0\0+?)\1+$0'

Anno Siegel

unread,
Jul 28, 2005, 5:14:02 PM7/28/05
to
Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:
> Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXLVIII
> September MCMXCIII in <URL:news:dc909g$gc2$2...@mamenchi.zrz.TU-Berlin.DE>:
> () Abigail <abi...@abigail.nl> wrote in comp.lang.perl.misc:
> () > Anno Siegel (anno...@lublin.zrz.tu-berlin.de) wrote on MMMMCCCXLVII
> () > September MCMXCIII in <URL:news:dc5vo5$iuc$1...@mamenchi.zrz.TU-Berlin.DE>:

[multiple inheritance]

> Unless you create some kind of has-a relationship. But this 'defect'
> isn't restricted to inside-out objects. Whatever you do, it's going to
> be hard to merge 2 hashes and 3 arrays. (Merging a single hash and a
> single array would still be possible by overloading the object to have
> @{} and %{} magic).

Overloading looks attractive and may work in specific cases, but the
restriction that no two classes be of the same type is too awkward to
be useful in a general class hierarchy. Also de-reference overloading
leads to problems with further inheritance.

> But in practise, the wide-spread practise (sic) of configuring an object
> in the constructor makes it already impossible to do MI without falling
> back on a has-a relationship.

That's an interesting remark, and if I ever get that inheritance paper
written it will make an appearance there in one form or another.

[...]

> () Instead, let me add a thought that is only loosely related. It seems
> () to me that inheritance and encapsulation don't go together (anywhere,
> () not only in Perl) in one respect. When it comes to overriding some
> () of the original methods, you must know how the methods in the base class
> () use (call) each other in order to predict the result. On the other hand,
> () that's an implementation detail that shouldn't concern the inheriting
> () class. I don't see how that can be resolved.
>
> Well, IMO, it's a bad idea to override a proper subset of related methods.

Quite so, but how do you know which methods are related?

> A lot of inheritance is done without overriding any methods - they are
> merely adding functionality, not overriding any. Then you don't have
> the problem you describe above. Furthermore, a lot of overriding is done
> while still calling the overridden method using SUPER.

Sure, a lot can be done without overriding. A lot of useful OO applications
don't even use inheritance. But then, it is only overriding that lets
old code call new code in OO. If you don't need that feature, mere
delegation will do. So, for me, overriding is one of the more interesting
aspects of inheritance.

> But if you have a statistical object with two methods, 'add' to add a
> new number to the set, and 'average' to return the average of the set,
> overriding either of 'add' or 'average', without calling SUPER:: is
> unlikely to work properly.

Funny... the example I had in mind was also a statistical package, where
the user would have to know whether or not ->variance called ->mean before
overriding ->mean to calculate (say) the geometric mean. But the problem
occurs in everyday programming. When inheriting from Tie::Handle, which
of WRITE, PRINT, and PRINTF do you override to get what effect? Only
the source (or experimentation) will tell.

David Combs

unread,
Aug 9, 2005, 6:57:47 AM8/9/05
to
In article <dbjq74$jgn$1...@mamenchi.zrz.TU-Berlin.DE>,

Anno Siegel <anno...@lublin.zrz.tu-berlin.de> wrote:
>A. Sinan Unur <1u...@llenroc.ude.invalid> wrote in comp.lang.perl.misc:
>> anno...@lublin.zrz.tu-berlin.de (Anno Siegel) wrote in
>> news:dbje2p$cp9$1...@mamenchi.zrz.TU-Berlin.DE:
>>
>> > The code for the base class is mostly unchanged. The only difference
>> > is that it inserts a do-nothing method (one that just returns its
>> > object) into all of its accessors (not in other methods). So if the
>> > accessor was
>> >
>> > sub alpha { $_[ 0]->[ 0] }
>> >
>> > it becomes
>> >
>> > sub alpha { $_[ 0]->parent->[ 0] }
>> > # ...
>> > sub parent { shift }
>>
>> [ rest of the discussion and code snipped ]
>>
>> Anno:
>>
>> I wanted to thank you very much for this series of posts, especially
>> this last one. I found it very informative.
>
>Thankyou. It's nice to be appreciated. [As Brian (Nobull) just said in
>another thread.]
>
>In fact, I think I'll make a (not much) more extensive writeup of this
>material and put it on the web (at least). The final trick deserves
>publicity, if I say so myself, but even without it, more awareness of
>accessors and their significance would help OO programming in Perl.
>
>Anno


WHERE, WHERE?

WHEN, WHEN?

IF, IF?


Thanks from *lots* of people!

David

Anno Siegel

unread,
Aug 9, 2005, 3:42:34 PM8/9/05
to
David Combs <dkc...@panix.com> wrote in comp.lang.perl.misc:

> In article <dbjq74$jgn$1...@mamenchi.zrz.TU-Berlin.DE>,
> Anno Siegel <anno...@lublin.zrz.tu-berlin.de> wrote:

[Inheritance in Perl]

> >In fact, I think I'll make a (not much) more extensive writeup of this
> >material and put it on the web (at least). The final trick deserves
> >publicity, if I say so myself, but even without it, more awareness of
> >accessors and their significance would help OO programming in Perl.
> >
> >Anno
>
>
> WHERE, WHERE?
>
> WHEN, WHEN?
>
> IF, IF?
>
>
> Thanks from *lots* of people!

I'm working on it, but it's going slow. Some of the problems in Perl OO
don't exist in more mainstream OO languages, so there are no textbooks
to steal from :)

0 new messages