in reply to new() function: incorrect?

If they wouldn't explain or discuss, I'd say you were well out of it !

I've always worried that the writer of the new() cannot control how it's called, given that any of:

my $foo = Bob::MyObject->new(...) ; # or new Bob::MyObject ... my $foo = $bar->new(...) ; my $foo = Bob::MyObject::new(...) ;
will invoke new(). The last can be distinguished if there are no arguments, and I've seen:
my $class = ref($proto) || $proto || __PACKAGE__ ;
recommended. But it's essentially ambiguous when arguments are present -- I wish for a prototype or other gizmo that would insert an undefined class/object argument when not called as a method.

You can give sub new an empty prototype to ensure that any Bob::MyObject::new calls are either unambigious at run-time or errors at compile-time. (Remembering that method calls ignore prototypes.)

I see the argument that $obj->new(...) is ambiguous, to the extent that, without checking what it does, the programmer doesn't know whether it's: (a) an instance of TMTOWTDI for Class->new(...) (or new Class ...); or (b) an overloading of new meaning clone. Perl Best Practices points out that $foo->new(...) may be a class or an object invocation, so argues that overloading is ambiguous and should be avoided.

Conventions help us reduce complexity, so not overloading new looks reasonable to me. YMMV

Now, if your new is never a clone operation, why would you want to $foo->new(...) -- unless $foo contains a class name (not an object) ? In the interests of, I think, simplicity, the modern advice appears to be to not accept $obj->new(...) -- so the common my $class = ref($proto) || $proto ; spell is deprecated (at least by some).

Of course, if the programmer doesn't provide the right parameters to your object's new you may choose simply to dump them on their backside with a run-time error (deliberately or by omission) -- in some cases, you may have no choice. I could suggest that in the case of $obj->new(...) you have a choice. But, if you go around pandering to slack programmers who ought to know better, how are they going to learn ? Really.

[In the context of cargo-cults: I guess you could say that not allowing for $obj->new(...) looks sufficient to eliminate slack practice -- whether it's necessary I leave open.]

Replies are listed 'Best First'.
Re^2: new() function: incorrect?
by lukeyboy1 (Beadle) on Nov 12, 2008 at 14:18 UTC
    I must admit that whenever I've been coaching people on creating new objects, I almost always tell them to declare an object like this:
    my $objectBlah = Blah::Object->new();
    I guess my reasoning behind this is that you should always be clear on creating a new instance of an object. I can't think of too many instances where I'd do
    my $foo = $bar->new();
    ...that just wouldn't, generally, cut the mustard with me -- unless you *really* needed another instance of the same object to do other stuff with. As I write this, I was trying to think of when I've needed to do this exact thing, and I honestly can't think of any instances that I've done that.

    However -- that may merely be an indictment of how I like to design my objects and code, generally.....!

    Also, I, personally dislike the following syntax:
    my $foo = new Bob::Object;
    I can't think of an exact reason -- probably just that I think that perl's syntax is nearly always based around using something like (in the case of reading a constant item that you've set up in your object framework) :-
    my $constantStuff = Bob::Constants::CONSTANT_STUFF;
    Adding in something like this:
    my $bob = new Bob::Object;
    ...just doesn't fit (in my head at least) with the nice perl way of doing things.

    I know my reason doesn't make too much sense: I just like a bit of consistency........!

    PS I'm actually really enjoying this conversation about something as simple as the best new() function to use. It reminds me of why I love perl so much.......!

      I wouldn't recommend:

      $obj->new(...) ;
      either. And, if I ever wanted to have a new object of the same class as another I'd prefer:
      ref($obj)->new(...) ;
      because (once you've worked out WTF is happening) it says exactly what is intended.

      However, on the general basis "Be strict in what you send, but generous in what you receive", throwing a run-time error at $obj->new(...) strikes me as ungenerous. Noting that perlobj for 5.10 (and 5.8.8) describes how to cope with this eventuality -- as the fourth in a sequence of increasingly complete object constructors.

      Or even:
      Bob::Object::new();
      to correct my last example. It's a method, so deserves the use of -> as far as I'm concerned.

      \end belligerent rant! :)