Ha! Yes, that works because you have been careful to implement the name field in inside-out manner. The trouble begins when you want to combine the Matrix class with a foreign (non-inside-out) class.# -*- Perl -*- use strict; use warnings; package Matrix::Named; use Scalar::Util qw/refaddr/; use base 'Matrix'; { my %name;
Say I've picked up your nifty Matrix class from somewhere, and this this lovely Angle class from somewhere else. I want to combine them in a class MyAngle so that matrix operations can be applied to an angle and refer to the corresponding rotational matrix.
Unfortunately, Angle is implemented in the traditional way as a (scalar) ref to the numeric value.
package Angle; use strict; use warnings; use constant PI => 4*atan2( 1, 1); use constant RAD => 180/PI; sub cre { bless \ my $angle, shift } sub new { my $class = shift; $class->Angle::cre->Angle::init( @_); } sub init { my $obj = shift; $$obj = _get_angle( @_); $obj; } sub rad { ${ shift() } }; sub deg { ${ shift() }*RAD } sub _get_angle { my $angle; if ( @_ == 1 ) { $angle = shift; } else { my %spec = @_; $angle = exists $spec{ deg} ? $spec{ deg}/RAD : $spec{ rad}; } modulo( $angle, 2*PI); } use POSIX; sub modulo { my ( $x, $y) = @_; $y ? $x - $y*POSIX::floor( $x/$y) : $x; } 1;
This relies on the possibility to replace the body of an inside-out object, (normally an undefined scalar) with some foreign object of any provenience, (also a scalar in this case, but with significant content) so that its methods work without a hitch. This approach won't work with a hybrid class where the body is required to be code.#!/usr/local/bin/perl use strict; use warnings; $| = 1; use Vi::QuickFix; # Definition of MyAngle below my $alpha = MyAngle->new( rad => atan2( 1, 1)); printf "Angle: %s (%s deg)\n", $alpha->rad, $alpha->deg; # Angle func +tions print "Matrix:\n$alpha\n"; # show the matrix representation ################################################## package MyAngle; use lib 'lib'; use base 'Angle'; use base 'Matrix'; sub new { my $class = shift; $class->Angle::cre->MyAngle::init( @_); } sub init { my $obj = shift; $obj->Angle::init( @_); $obj->Matrix::init( cos( $_), -sin( $_), sin( $_), cos( $_)) for $obj->rad; $obj; } __END__
Anno
PS: If you actually want to run the code against the inside-out implementation of Matrix use the updated code from my previous posting. There was a bug in the original that would have been a show-stopper.
In reply to Re^3: Agile syntax (abuse?)
by Anno
in thread Agile syntax (abuse?)
by blazar
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |