Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Re: Re: A different OO approach

by fruiture (Curate)
on Dec 15, 2002 at 11:47 UTC ( #219986=note: print w/ replies, xml ) Need Help??


in reply to Re: A different OO approach
in thread A different OO approach

I can't agree:

All attributes have global scope.

What does that mean? What global scope shall these attributes have?

Typing $self->{fo} when you meant to type $self->{foo} won't give you a compile time error.

You can't solve this problem as long as you use a hash at all. But the danger can be limited to inside the class by enforcing accessor methods. Your Code doesn't help this either.

You can't inherit from classes implemented with non-hash references.

You can. You cannot implement non-hash objects using the OO module, but you can inherit from any object, because _your_ class' data is kept somehwere else. Anyways: the new() was in question. It's probably no good idea, although you're always allowed to override it.

oo_get/set allows you to get the attribute from any class through your optional third argument.

Just as Perl gives you symbolic references. This is for example needed when you create accessor methods automatically.

The idea of putting the data back into the object seperated by classes is great. It makes the object classically serializable and gets us rid of complicated DESTROY methods because it's all in one place. "Ay, there's the rob", it is then impossible to inherit from classes that don't use that new scheme.

If you can accept it that you only need the new scheme for new classes and not for subclassing others, it's quite easy to put that abstraction into a superclass as well (also avoiding use of __PACKAGE__):

package OO; use strict; use warnings; # A constructor sub oo_create { my $class = shift; bless {}, $class; } # Set Data reference for current class sub oo_set { my $obj = shift; my $val = shift; my $class = @_ ? shift : caller; $obj->{ $class } = $val; } # Get Data reference for current class sub oo_get { my $obj = shift; my $class = @_ ? shift : caller; $obj->{ $class }; } 1;

In use that's:

package Foo; use base 'OO'; sub new { my $class = shift; ( my $self = $class->oo_create )->oo_set( [] ); # array based object! $self } sub bar { my $self = shift; my $data = $self->oo_get; $data->[0] = shift if @_; $data->[0] }

You could now even use OO as library, not as class...

I think we're on the right way ;)

--
http://fruiture.de


Comment on Re: Re: A different OO approach
Select or Download Code
Re^3: A different OO approach
by Aristotle (Chancellor) on Dec 15, 2002 at 13:31 UTC

    If you can make everyone adhere to your concept then it will indeed work. But that's not a whole lot different from saying that if everyone puts their data in a hash, prepends their attributes with their package name, and uses accessors only, we avoid all the problems.

    But you don't know if everyone does.

    With inside out objects, you don't have to care what your superclass does. It can be implemented in any way. Inside out objects always work.

    Your approach is nice in theory, but violates the principle that classes inheriting from each other should not - and should not have to - know anything about their base class other than the public interface.

    Makeshifts last the longest.

      That's exactly what i meant: You cannot subclass something unknown without using an inside-out object.

      --
      http://fruiture.de
Re^3: A different OO approach
by adrianh (Chancellor) on Dec 15, 2002 at 16:39 UTC
    What does that mean? What global scope shall these attributes have?

    You can get at the attributes of a class in it's sub-classes, for example:

    package Inc; use base 'OO'; sub next { my $self = shift; my $next = $self->oo_get('inc'); $self->oo_set('inc', ++$next); return($next); }; package Inc2; use base qw(Inc); sub current { my $self = shift; $self->oo_get('inc', 'Inc'); };

    Some people consider being able to do this sort of thing bad. You cannot hide implementation details so you can change them without affecting other classes. With inside-out objects the hash can be lexically scoped to the class - so there is no way you can get at it from the super-class.

    { package Inc; my %Value = (); sub new { bless [], shift; }; sub next { ++$Value{+shift}; }; }; { package Inc2; # ... no way to get at %Value here ... };

    While you may not want this feature yourself, it is something that inside objects can do, that your implementation cannot.

    Typing $self->{fo} when you meant to type $self->{foo} won't give you a compile time error.
    You can't solve this problem as long as you use a hash at all. But the danger can be limited to inside the class by enforcing accessor methods. Your Code doesn't help this either.

    You can solve it with inside out objects - one of their great advantages. For example, If I made a typo when I implemented Inc using your module.

    sub next { my $self = shift; my $next = $self->oo_get('inc'); $self->oo_set('incc', ++$next); return($next); };

    I won't get any compile-time error - it will just fail silently.

    If make a typo with the field name with the inside-out object implementation.

    sub next { ++$Valuee{+shift}; };

    I'll get a compile time error with use strict because %Value isn't defined.

    I know the code I showed didn't solve the problem. I wasn't trying to. I was demonstrating that you could get most of what your modules gives you using hash-based objects, rather than a global hash.

    You can't inherit from classes implemented with non-hash references.
    You can. You cannot implement non-hash objects using the OO module, but you can inherit from any object, because _your_ class' data is kept somehwere else. Anyways: the new() was in question. It's probably no good idea, although you're always allowed to override it.

    If you read what I wrote again, you'll see I said:

    Having your own new() method makes mixing this into an existing class hard.

    Having a new function means that you have to take care with the order of your classes in the inheritence hierarchy, otherwise your new will override the new from the other class you are inheriting from.

    For example:

    package AppointmentDate; use base qw(OO Date::Simple); sub appointment { my ($self, $appointment) = @_; $self->oo_set('appointment', $appointment) if $appointment; return( $self->oo_get('appointment') ); };

    won't work because it needs to be use base qw(Date::Simple OO) to get the correct new() method called. In general classes that you intend to mixin to existing class hierarchies should avoid constructors.

    oo_get/set allows you to get the attribute from any class through your optional third argument.
    Just as Perl gives you symbolic references. This is for example needed when you create accessor methods automatically.

    Just because you can do it, doesn't mean that it's a good idea :-) The fact that you cannot do this with Abigail-II's implementation of inside out objects as lexically scoped hashes is a feature, not a bug.

    There are many other ways to make accessor methods without having the ability to get arbritary attributes from objects (e.g. with source filters or like this).

    The idea of putting the data back into the object seperated by classes is great. It makes the object classically serializable and gets us rid of complicated DESTROY methods because it's all in one place. "Ay, there's the rob", it is then impossible to inherit from classes that don't use that new scheme.

    Completely true. The point I was trying to make was that this was the only advantage your system gave you - while dropping the other advantages of using lexically scoped hashes:-)

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://219986]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (6)
As of 2014-07-29 21:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (228 votes), past polls