In Perl, is there any harm in creating a subroutine with the same name as a package?
Say I have a package called My::Pkg
, and that package has a ->new(...)
class method to instantiate new objects:
package My::Pkg;
sub new {bless {@_[1..$#_]} => $_[0]}
Is there any harm in defining the following subroutine:
sub My::Pkg {@_ ? My::Pkg::new('My::Pkg', @_) : 'My::Pkg'}
So that someone could write:
my $obj = My::Pkg one => 1, two => 2;
Rather than:
my $obj = My::Pkg->new(one => 1, two => 2); # which still works, but is longer
I like the terseness of the package-named-constructor-subroutine method, but I am interested to know if there are any hidden gotchas to this technique that I have not thought of.
Update:
Inheritance works correctly, as shown by the example here:
开发者_StackOverflow社区{package a; sub new {say "a::new [@_] ", $_[0]->init}}
{package b; our @ISA = 'a'; sub init {"(b::init [@_])"}}
{package a::b; our @ISA = 'b';}
sub a::b {print "absub [@_], "; 'a::b'}
# a::b() called with no args, returns 'a::b', which then becomes 'a::b'->new(...)
a::b->new; # absub [], a::new [a::b] (b::init [a::b])
a::b->new(1, 2, 3); # absub [], a::new [a::b 1 2 3] (b::init [a::b])
# no call to `a::b()` but otherwise the same:
'a::b'->new; # a::new [a::b] (b::init [a::b])
'a::b'->new(1, 2, 3); # a::new [a::b 1 2 3] (b::init [a::b])
new a::b::; # a::new [a::b] (b::init [a::b])
new a::b:: 1, 2, 3; # a::new [a::b 1 2 3] (b::init [a::b])
Interestingly the only thing so far that is different is that the following 2 lines become syntax errors:
new a::b;
new a::b 1, 2, 3;
Which is a syntax error for the same reason some_undefined_sub some_defined_sub;
is one.
If the new
subroutine is defined, it is parsed as new( a::b(...) )
which is normal for two adjacent bareword subroutines.
Personally, I am ok with new a::b
becoming a syntax error, the unambiguous version new a::b::
will always work as tchrist helpfully points out below.
That’s precisely why
$thingie = new Some::Class one => 1, two => 2;
or
$thingie = new Some::Class::
one => 1,
two => 2,
;
exists, so just use that.
But yes, I think you will get yourself into a whole slew of troubles, since I am the only person in the world who bothers to package-quote. I don’t have time right now to dig through my old problem-testing code, but I am pretty sure this will eventually make you cry if you go down the road you’re speaking of.
"I am interested to know if there are any hidden gotchas to this technique that I have not thought of."
I think a hidden gotcha is lack of consistency with how most OOP langs define constructors. Obviously, Perl likes its TMTOWTDI philosophy, but someone having to maintain your code later when/if you're not around may take more time to understand what your code is doing.
Also, what if you want to add another constructor? I've seen some classes where there are constructors named: new, new_from_file, etc. Maybe not the best design, but it did clarify that an object was constructed in a unique way.
精彩评论