This queue is for tickets about the Class-Std CPAN distribution.

Report information
The Basics
Id:
20966
Status:
open
Priority:
Low/Low
Queue:

People
Owner:
Nobody in particular
Requestors:
ROBN [...] cpan.org
Cc:
AdminCc:

BugTracker
Severity:
Wishlist
Broken in:
(no value)
Fixed in:
(no value)



Subject: No way to set a superclass constructor argument from a derived class
Class-Std 0.0.8 Perl 5.8.8 Linux 2.6.16 In days gone by, I might have done this: package myclass; use Carp qw(croak); sub new { my ($class, $value) = @_; croak "required value missing" if @_ == 1 or !$value; return bless \$value, $class; } package mysubclass; use base qw(myclass); sub new { my ($class) = @_; return bless $class->SUPER::new(23), $class; } I see no way to do this with Class::Std. My instinct was to do this: package myclass; use Class::Std; my %value :ATTR( :init_arg<value> ); package mysubclass; use base qw(myclass); sub BUILD { my ($self, $ident, $args) = @_; $args->{value} = 23; } Reading Class/Std.pm, I see why this doesn't work, but I think it should. At least there should be some mechanism to make this possible. My "workaround" is to remove the :init_arg from myclass, and setup a START that croaks if the value isn't there, or sets it if it is. In other words, I'm doing what I would have done pre-Class::Std, and not taking advantage of its whole argument checking setup. Was there a design rationale for not allowing this? Can I get something like this in the next release? Otherwise, if you think the idea is fine, I can try to cobble together a patch myself. Cheers, Rob.
Subject: Re: [rt.cpan.org #20966] No way to set a superclass constructor argument from a derived class
Date: Thu, 17 Aug 2006 17:59:27 +1000
To: bug-Class-Std@rt.cpan.org
From: Damian Conway <damian@conway.org>
Rob writes:
Show quoted text
> I see no way to [wrap a constructor] with Class::Std.
It's easy: package myclass; use Class::Std; my %value :ATTR( :init_arg<value> :get<value> ); package mysubclass; use base qw(myclass); sub new { my ($class, $args) = @_; return $class->SUPER::new({ %{$args}, value=>23 }); } package main; my $obj = mysubclass->new({value=>42}); print $obj->get_value(); Damian
From: ROBN@cpan.org
Show quoted text
> package mysubclass; > use base qw(myclass); > > sub new { > my ($class, $args) = @_; > return $class->SUPER::new({ %{$args}, value=>23 }); > }
Sorry, I wasn't clear. In my app, mysubclass is another Class::Std class. Relevant snips: package Unit; use Class::Std; my %race :ATTR( :name<race> ); my %location :ATTR( :get<location> :set<location>); my %energy :ATTR( :get<energy> ); package Army; use base qw(Unit); use Class::Std; my %size :ATTR( :name<size> ); my %morale :ATTR( :name<morale> ); Now the enemy armies have a bunch of extra stuff related to the AI, so they get their own class. I want the constructor to initialise Unit::race to mark them as an enemy. The most obvious way to do this (to me) was: package EnemyArmy; use base qw(Army); use Class::Std; my %orders :ATTR( :init_arg<orders> :get<orders> ); my %target :ATTR( :init_arg<target> :get<target> ); sub BUILD { my ($self, $ident, $args) = @_; $args->{race} = Race::FOUL; } ie let the derived class initialise args for the base class constructors. That doesn't work, of course. My workaround is removing init_arg from Unit::race, then having Unit::START, Army::START check for $args->{race} and call $self->set_race if its there, or croak if its not. Obviously that sucks. Thanks, Rob.


This service runs on Request Tracker, is sponsored by The Perl Foundation, and maintained by Best Practical Solutions.

Please report any issues with rt.cpan.org to rt-cpan-admin@bestpractical.com.