Replies: 2 comments 1 reply
|
Works for me. Being able to support the singleton pattern use-case and a single positional constructor parameter are useful and important features. |
|
I realize I'm out of my depth here, but ... Under your proposal, could One of the things I love about Perl 5's original ur-object system versus more traditional object systems such as (say) Java's is that In more traditional object systems the user of a class must know whether to call a factory, or just instantiate the object directly. If a factory is needed, the user needs to figure out what it is called. At the very least this seems to me to violate the principal of Laziness, which I would like to see preserved in any core Perl object system. |
Uh oh!
There was an error while loading. Please reload this page.
First off: I don't like the name but I spent ages thinking on this and didn't come up with anything better, so... Suggestions welcome there ;)
Object::Padhas a class attribute called:lexical_newwhich has an effect on how the constructor method for a class is created. I'd like to suggest the same thing for core perl'sclassfeature.Every class gets a constructor method automatically created, which takes parameters and does all the work of assigning them into fields, creating the actual object instance, running the
ADJUSTblocks, and so on. Normally, without the attribute applied to the class, this method is then installed in the package for that class as a symbolically-named method called "new", meaning that any other code can invoke it by its publicly-visible name.But sometimes you don't want that to be publicly visible. A publicly-visible constructor means that any other code is always able to create new instances of your class. There could be reasons you don't want that to happen.
For this reason, the
:lexical_newattribute changes the generated constructor method so that it isn't installed as publicly-visible symbolic name in the class package, but instead is installed lexically within the block scope of the class as the "&new" lexical. This makes it visible to other code that the class package has chosen to provide, but invisible to outside callers. This makes it possible to provide other shapes of object construction; for example singleton or factory patterns. Code inside the class can provide class methods that make decisions about what constructor to invoke and how, or whether even to at all. The class can then be relatively confident that no outside code can bypass those wrappers, because theClass->newmethod is not visible.class AUniqueInstance :lexical_new { my $instance; # It's the Singleton pattern sub instance ( $ ) { return $instance //= __PACKAGE__->&new; } } ok( AUniqueInstance->instance == AUniqueInstance->instance, "It's a singleton" ); AUniqueInstance->new; # throws an exceptionIn fact this also makes it possible to provide constructors which take different shapes of arguments, by manually writing a
newmethod that dispatches to the lexical one by reshaping its arguments. It can be especially handy for making object classes that only have one obvious construction parameter, allowing callers to pass it in positional rather than named style.class Path :lexical_new { field $filename :param :reader; method new :common ($filename) { return $class->&new( filename => $filename ); } } my $null = Path->new( "/dev/null" );Though I should probably point out it's not always ideal to do that kind of thing, as it can make subclasses more difficult to reason about. But it's certainly possible. :)
All reactions