再度、すべてに対する等価性
今回やったこと
- DollarクラスおよびFrancクラスの基底クラスMoneyを作成
- equals()メソッドおよび関連メソッドを基底クラスに移動
クラス間の重複を取り除いたので大分すっきりしました。あとはコンストラクタとtimesメソッドの重複を取り除くといい感じになります。
調べた限りでは、クラスを継承する場合は、@ISAを直接いじるより、use baseを使った方がいいみたいですね。
lib/Money.pm
package Money; use strict; use warnings; use version; our $VERSION = qv('0.0.3'); use overload "==" => \&equals, "eq" => \&equals, "!=" => \¬_equals, "ne" => \¬_equals, '""' => \&string; sub equals { my ($self, $money) = (@_); return $self->{amount} == $money->{amount}; } sub not_equals { my ($self, $money) = (@_); return not $self->equals($money); } sub string { my ($self) = (@_); return $self->{amount} . ' (' . __PACKAGE__ . ')'; } 1; package Dollar; use strict; use warnings; use base 'Money'; use overload "*" => \× sub new { my ($class, $opts) =(@_); return bless $opts, $class; } sub times { my ($self, $multiplier) = (@_); return new Dollar({amount => $self->{amount} * $multiplier}); } 1; package Franc; use strict; use warnings; use base 'Money'; use overload "*" => \× sub new { my ($class, $opts) =(@_); return bless $opts, $class; } sub times { my ($self, $multiplier) = (@_); return new Franc({amount => $self->{amount} * $multiplier}); } 1;
t/01money.t
use strict; use warnings; use Test::Class; Test::Class->runtests; package TestMoney; use strict; use warnings; use base 'Test::Class'; use Money; use Test::More; sub test_multiplication : Test(2) { my $five = new Dollar({amount => 5}); is($five * 2, new Dollar({amount => 10})); is($five * 3, new Dollar({amount => 15})); } sub test_equality : Test(4) { ok(new Dollar({amount => 5}) == new Dollar({amount => 5})); ok(new Dollar({amount => 5}) != new Dollar({amount => 6})); ok(new Franc({amount => 5}) == new Franc({amount => 5})); ok(new Franc({amount => 5}) != new Franc({amount => 6})); } sub test_franc_multiplication : Test(2) { my $five = new Franc({amount => 5}); is($five * 2, new Franc({amount => 10})); is($five * 3, new Franc({amount => 15})); } 1;