Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

(jeffa) 3Re: My first stab at OO perl...

by jeffa (Bishop)
on Jul 16, 2002 at 17:26 UTC ( [id://182171]=note: print w/replies, xml ) Need Help??


in reply to Re: (jeffa) Re: My first stab at OO perl...
in thread My first stab at OO perl...

Calling an instance constructor? Yuck! If you want to clone an object, use the right tool, such as Clone:
use strict; use Clone qw(clone); my $foo = foo->new(5); my $bar = clone($foo); print $bar->id(), "\n"; package foo; use strict; sub new { my ($class,$id) = @_; my $self = { id => $id || 42, }; return bless $self,$class; } sub id { my ($self,$id) = @_; return $self->{id} unless $id; $self->{id} = $id; }
or provide your own clone() method for the class. I really recommend that you read TheDamian's excellent book, Object Oriented Perl, by the way.

jeffa

L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
B--B--B--B--B--B--B--B--
H---H---H---H---H---H---
(the triplet paradiddle with high-hat)

Replies are listed 'Best First'.
Re: (jeffa) 3Re: My first stab at OO perl...
by Theseus (Pilgrim) on Jul 16, 2002 at 17:54 UTC
    So you agree that calling instance constructors is a bad thing, but you don't agree that inserting code to prevent it from being done(or at least return the same result as if it had been done correctly) is a good thing? That's exactly what I don't understand.

    I personally would never call $newobject = $oldobject->new, but I can't say that nobody who uses a class I design won't, and I want to account for that.

    I'd like to hear your thoughts on the subject(and I'd love to hear merlyn's, if he sees this thread).

      sub new { my $classname = shift; return undef if ref $classname; # Other stuff here. }
      Just because Perl doesn't do it automatically doesn't mean you can't write gatekeepers on your own functions.

      ------
      We are the carpenters and bricklayers of the Information Age.

      Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

        That is indeed an option, but I'm of the school of thought that it's better for a program or operation in a program to silently catch an error and correct it for the user than to just fail outright.
        I've read that post, and that's why I said I would like to hear merlyn's thoughts. Basically, that post says the same thing I just said: You shouldn't ever need to call the new method on an instance.

        However, that doesn't mean that as the designer of a class, you can't provide the proper instructions to prevent an error when someone ELSE calls new on an object they got from your class, be it intentional or otherwise.

        Personally, I consider the following two statements to be equally as ridiculous:

        Don't use ref($proto) because users of your module/class should never call a constructor on an instance.

        Don't check to make sure open() succeeded because a user should always make sure they're running your program with the proper permissions to open a file.

        Either way, you're depending on someone else not to break your code, and that can't be good.

Re: (jeffa) 3Re: My first stab at OO perl...
by frag (Hermit) on Jul 17, 2002 at 03:49 UTC
    Although you should know that Damian uses ref($caller) extensively in his book (see all the CD::Music examples). I'm not saying that's right, but it makes the context of the recommendation to read the book sound sort of self-contradictory.

    Me, I've been castigated by merlyn for using ref($caller), and I've (sort of) come around to his view. That is, $obj->new() just always struck me as a perfectly reasonable way to obtain a new, 'blank' object of the object's class. Expecting it to clone just never made any sense to me (if you meant it to clone, you'd've named it clone(), right?). But I've come to sense that I'm in the minority on this one, and calling $obj->new() hasn't ever been truly necessary in my code anyway; if this is going to be that confusing to that many people, then it's a de facto bad idea. (Though still, I'd like to know how many people would really be confused by this, and how many wouldn't be, but are just saying that someone else may get confused.)

    -- Frag.

      You almost got me. :)

      On page 103, TheDamian explains that calling a 'constructor' as an object method is a lazy way to copy an object, but observe what happens when you change an object's attributes at runtime and try to clone it:
      use strict; use Clone qw(clone); my $foo = foo->new(); $foo->{spam} = {spam =>'eggs'}; my $bad_clone = $foo->new(); my $good_clone = clone($foo); $bad_clone->{spam}->{spam} or warn "bad has no eggs"; $good_clone->{spam}->{spam} or warn "good has no eggs"; package foo; use strict; sub new { my $class = shift; my $proto = ref($class) || $class; return bless {}, $proto; }
      TheDamian also explains on page 105 that
      While many experts view the overloading of constructors as object copiers to be a natural extension of their functionality, others consider the technique unintuitive, too subtle, and more likely to produce obscure and hard-to-maintain code.
      and on page 106
      If you have a choice, it's probably better to code a seperate clone method. Apart from keeping your individual methods simpler and less prone to bugs, the method's name will force client code to be more clearly self-documenting.

      jeffa

      doesn't like spam
        Still, that's after using ref($caller) in all the preceding examples. Ditto in the 'final version' of CD::Music (p.114). And you've got to admit, "probably better" aint much of a condemnation.

        -- Frag.

Re: (jeffa) 3Re: My first stab at OO perl...
by v_thunder (Scribe) on Jul 17, 2002 at 03:57 UTC

    I'm reading through perltoot(1), trying to grok perl's way of doing OO, and it actually recommends doing just what Theseus did. From perltoot:

    sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; $self->{NAME} = undef; $self->{AGE} = undef; $self->{PEERS} = []; bless ($self, $class); return $self; }

    So is this only recommended if you plan to allow for inheritance? Or did I miss something?

    -Dan

      Here I go replying to myself again... :-)

      Your code *does* allow for inheritance, it just doesn't allow for someone to create a new instance by calling $foo->new() on an already made instance. Right?

      So: I now get it. Though, personally, I'd rather have it die immediately than not work correctly. And, btw, it's rather confusing to have that bit in perltoot(1).

      Thanks for making me think about this! :)

      -Dan

        No... The way my code is, it WILL allow for you to create a new instance by calling $object->new() on an already running instance, if you remove the code that merlyn disapproves of, it won't die, but it will silently work incorrectly. That's my gripe with it.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2024-04-26 00:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found