Thread

Posted on Thu Jan 12 23:35:07 2006 by earl
a subclass doesn't have much control over the initialization of its superclass

The following example is C++inheritance, where the subclass controls how the superclass is initialized. Sometimes you want to say A is-a B, but you don't want to initialize B in the general fashion. For example, you may want to have new default parameters for the attributes of B.

Is there an elegant way to do this, while using the inside-out paradigm? Here, a subclass doesn't have much control over the initialization of its superclass.

IMHO, the best solution is to turn the is-a relation into a has-a relation. But, that's not what you really want.

class Point { private double x, y; Point (double x, double y) { this.x = x; this.y = y; } double getX () { return x; } double getY () { return y; } } class Circle extends Point { private double radius; Circle (double x, double y, double radius) { super (x, y); // Call Point (double x, double y). this.radius = radius; } double getRadius () { return radius; } }
Direct Responses: 1625 | Write a response
Posted on Sat Jan 14 06:26:31 2006 by jdhedden in response to 1622
Re: Subclass Controlling Superclass Initialization
    Is there an elegant way to [allow a subclass to control object initialization
    of a parent class], while using the inside-out paradigm?

The short answer is 'yes'. However, I really don't think this kind of control is necessary. In general, if someone felt they really needed to do this, then my opinion would be that their object design is probably flawed.

For instance, your example doesn't require this kind of control:
package Point; { use Object::InsideOut; my @x :Field('Get' => 'getX'); my @y :Field('Get' => 'getY'); my %init_args :InitArgs = ( 'x' => { 'Field' => \@x, 'Type' => 'Numeric', 'Mandatory' => 1, }, 'y' => { 'Field' => \@y, 'Type' => 'Numeric', 'Mandatory' => 1, }, ); } package Circle use Object::InsideOut 'Point'; my @radius :Field('Get' => 'getRadius'); my %init_args :InitArgs = ( 'radius' => { 'Field' => \@radius, 'Type' => 'Numeric', 'Mandatory' => 1, }, ); } package main; MAIN: { my $circle = Circle->new( { 'x' => 3, 'y' => -4.5, 'radius' => 1.2 } ); }
Additionally, you can control which args apply to which classes:
my $circle = Circle->new( { 'Point' => { 'x' => 3, 'y' => -4.5, }, 'Circle' => { 'radius' => 1.2, } } );
However, if needed, the subclass could provide its own new() method that is a wrapper around Object::InsideOut's new() method. This was illustrated in an earlier thread in this forum.

Here's your example, coded with such a 'new() wrapper':
package Point; { use Object::InsideOut; my @x :Field('Get' => 'getX'); my @y :Field('Get' => 'getY'); my %init_args :InitArgs = ( 'x' => { 'Field' => \@x, 'Type' => 'Numeric', 'Mandatory' => 1, }, 'y' => { 'Field' => \@y, 'Type' => 'Numeric', 'Mandatory' => 1, }, ); } package Circle use Object::InsideOut 'Point'; my @radius :Field('Get' => 'getRadius'); my %init_args :InitArgs = ( 'radius' => { 'Field' => \@radius, 'Type' => 'Numeric', 'Mandatory' => 1, }, ); sub new { my ($thing, $x, $y, $radius) = @_; return ($thing->Object::InsideOut::new( { 'x' => $x, 'y' => $y, 'radius' => $radius } ); } } package main; MAIN: { my $circle = Circle->new(3, -4.5, 1.2); }
Write a response