in reply to Re: Thoughts on new 'class' OO in upcoming perl in thread Thoughts on new 'class' OO in upcoming perl
Of course, if you prefer to return undef in that case, you can have that, too: All you need to know is that stuff you used to write in the body of new now goes into the ADJUST phaser.
How? How do you prevent your OO system from throwing in case a mandatory parameter is missing and convince it to return undef instead? How do you convince it to return undef from within an ADJUST whateverscifiweaponyoudecidetocallit?
Your attribute based constructor abort is very limited and while throwing an exception inside an ADJUST thingie would likely abort the constructor ... after wasting time and resources in the constructors and AJDUST lasers of the parent class(es) ... there doesn't seem to be a way to return undef.
Your OO system's new doesn't look like bless on steroids. It sounds more like bless overdosed with antidepressants.
Deciding when to call parent constructor?
If it's something an ADJUST block can fix SHOW US HOW!
Jenda
1984 was supposed to be a warning,
not a manual!
Re^3: Thoughts on new 'class' OO in upcoming perl
by haj (Vicar) on Mar 18, 2023 at 21:13 UTC
|
How? How do you prevent your OO system from throwing in case a mandatory parameter is missing and convince it to return undef instead?
Good catch! I mixed up things here. It is definitely not possible to coerce a new method to return undef on failure. If you really want that, you need to write a custom constructor. I often write custom constructors, though mostly for other reasons.
The new core OO system didn't invent this behavior, though. It is quite common with many OO systems on CPAN: They write a constructor method new for you, according to some declarative syntax. Therefore, new is no longer a "user defined constructor method": It is rather a part of the language on the same level as bless (disregarding the specifics of its medication for now). In none of these OO systems you get a chance to call the parent constructor. They all claim that you don't need to call the parent constructor, and they all have some mechanism to deal with inheritance during construction. For the new core OO system, ADJUST blocks are that mechanism.
There are differences between the new core OO system and the popular CPAN OO systems, and these affect the construction of objects, in particular in an inheritance hierarchy:
- Moose (also Moo and Object::Pad) offer a BUILDARGS method to mangle the parameter list provided to new before object creation starts. The new core OO system (like e.g. Dios) does not have this, it only allows a hash-style parameter list. So, you could keep arbitrary constructor APIs when moving from bless-style OO to Moose, but you can not achieve that with core OO. This is the main reason why I write custom constructors these days: I want to have control over my constructor API.
- Child classes have no access to parent attributes unless there are (public) accessor methods for them. In Moose, you could always access the hash containing all fields, this is now gone. Also, Moose allowed to change a field declaration in a subclass with the has '+field' syntax, neither Object::Pad nor core OO allow this. This is sometimes an obstacle during object construction, and the discussion is still ongoing.
| [reply] |
|
Child classes have no access to parent attributes unless there are (public) accessor methods for them.
That does not make any sense to the way i do OO. Often enough, i write a base class which does the basics, like for instance, handling a websocket. Then i subclass this and override the empty methods in the base class i need to handle this specific websocket connection. I would still need access to all the stuff in the base class. Yes, technically, i could write accessors, but the would just bloat the code and make it slower. It wouldn't provide any benefits that i can see.
In fact, it might be contraproductive to provide public methods to access the internals in some cases. I might want to give the child classes the ability to fiddle with internal settings of the websocket, but not provide the object creator (? i mean the object that called new()) the same kind of access.
| [reply] |
|
Indeed, I guess that this design decision could be a major obstacle for adoption of the new core OO. It is a consequence of the intended encapsulation of classes: Fields without accessors are private to the class, and different classes (and roles) in a class hierarchy can use the same field name without conflicts.
There have been lengthy discussions about allowing subclasses direct access with an explicit "opt-in" mechanism (similar to protected in Java), and I would love to see that. However, this will not happen in the first version of core OO.
| [reply] |
|
This is what "protected" is for in other OO systems. The stuff you want hidden even from the subclasses is marked private, the stuff you want them to have access to is protected, the stuff you only want to access within the library is internal and only the stuff that's supposed to be ... erm ... public is public.
private and public on their own is NOT enough.
Jenda
1984 was supposed to be a warning,
not a manual!
| [reply] |
Re^3: Thoughts on new 'class' OO in upcoming perl
by tobyink (Canon) on Mar 19, 2023 at 12:03 UTC
|
How do you prevent your OO system from throwing in case a mandatory parameter is missing and convince it to return undef instead?
How do you prevent bless() from throwing in case a mandatory parameter is missing, and convince it to return undef instead?
my $data = undef;
my $object_or_undef = bless( $data, 'My::Class' );
(The above will throw an exception.)
The answer is you don't even try to stop bless bless from throwing. You wrap it in sub new { ... } so you have more control over how bless is called:
package My::Class {
sub new {
my ( $class, $data ) = @_;
return undef unless ref $data eq 'HASH';
bless $data => $class;
}
}
my $data = undef;
my $object_or_undef = My::Class->new( $data );
Similarly, if you don't want core OO's new to throw an exception when mandatory paramaters are missing, you wrap it in another method.
| [reply] [d/l] [select] |
|
| [reply] [d/l] [select] |
|
Only by convention. Conventions can be changed.
To an extent, Moose has already changed that convention. The new method generated by Moose can be a little inflexible, so many people write a wrapper constructor around it — new_from_foo or new_with_bar or whatever — and document that this should be used rather than calling new directly.
| [reply] [d/l] [select] |
|
|
|
|