views:

411

answers:

4

Many years ago I remember a fellow programmer counselling this:

new Some::Class;    # bad! (but why?)

Some::Class->new(); # good!

Sadly now I cannot remember the/his reason why. :( Both forms will work correctly even if the constructor does not actually exist in the Some::Class module but instead is inherited from a parent somewhere.

Neither of these forms are the same as Some::Class::new(), which will not pass the name of the class as the first parameter to the constructor -- so this form is always incorrect.

Even if the two forms are equivalent, I find Some::Class->new() to be much more clear, as it follows the standard convention for calling a method on a module, and in perl, the 'new' method is not special - a constructor could be called anything, and new() could do anything (although of course we generally expect it to be a constructor).

+16  A: 

See Indirect Object Syntax in the perlobj documentation for an explanation of its pitfalls.

brian d foy
I haven't read that man page in years; I really should read more of it. It's a shame 'new Some::Class' has so many pitfalls, as I like the way it reads better than 'Some::Class->new()'; One of the things I like most about Perl is the natural language feell to it. Oh well, time for a change.....
Joe Casadonte
+16  A: 

Using new Some::Class is called "indirect" method invocation, and it's bad because it introduces some ambiguity into the syntax.

One reason it can fail is if you have an array or hash of objects. You might expect

dosomethingwith $hashref->{obj}

to be equal to

$hashref->{obj}->dosomethingwith();

but it actually parses as:

$hashref->dosomethingwith->{obj}

which probably isn't what you wanted.

Another problem is if there happens to be a function in your package with the same name as a method you're trying to call. For example, what if some module that you use'd exported a function called dosomethingwith? In that case, dosomethingwith $object is ambiguous, and can result in puzzling bugs.

Using the -> syntax exclusively eliminates these problems, because the method and what you want the method to operate upon are always clear to the compiler.

friedo
+3  A: 

The indirect object syntax is frowned upon, for good reasons, but that's got nothing to do with constructors. You're almost never going to have a new() function in the calling package. Rather, you should use Package->new() for two other (better?) reasons:

  1. As you said, all other class methods take the form Package->method(), so consistency is a Good Thing

  2. If you're supplying arguments to the constructor, or you're taking the result of the constructor and immediately calling methods on it (if e.g. you don't care about keeping the object around), it's simpler to say e.g.

$foo = Foo->new(type => 'bar', style => 'baz');
Bar->new->do_stuff;

than

$foo = new Foo(type => 'bar', style => 'baz');
(new Bar)->do_stuff;
Sam Kington
A: 

Another problem is that new Some::Class happens at run time. If there is an error and you testing never branches to this statement, you never know it until it happens in production. It is better to use Some::Class->new unless you are doing dynamic programing.