生きている時(times)
- DollarクラスとFrancクラスのコンストラクタを共通化
- 通貨単位を返すcurrency()メソッドの実装
- times()メソッド内でのファクトリメソッドの使用
DollarクラスとFrancクラスでスーパークラスのコンストラクタを呼んでいますが、この処理はいらないような気がします。
今日は時間がないので1章だけ。
lib/Money.pm
package Money; use strict; use warnings; use Carp; use version; our $VERSION = qv('0.0.3'); use overload "==" => \&equals, "eq" => \&equals, "!=" => \¬_equals, "ne" => \¬_equals, '""' => \&string; sub new { my ($class, $opts) =(@_); croak 'Not exists amount option' if not exists $opts->{amount}; croak 'Not exists currency option' if not exists $opts->{currency}; return bless $opts, $class; } sub equals { my ($self, $money) = (@_); use Test::More; return $self->{amount} == $money->{amount} && ref $self eq ref $money; } sub not_equals { my ($self, $money) = (@_); return not $self->equals($money); } sub string { my ($self) = (@_); return $self->{amount} . ' (' . __PACKAGE__ . ')'; } sub dollar { my ($class, $opts) =(@_); $opts->{currency} = 'USD'; return Dollar->new($opts); } sub franc { my ($class, $opts) =(@_); $opts->{currency} = 'CHF'; return Franc->new($opts); } sub currency { my $self = shift; return $self->{currency}; } 1; package Dollar; use strict; use warnings; use base 'Money'; use overload "*" => \× sub new { my ($class, $opts) = (@_); return $class->SUPER::new($opts); } sub times { my ($self, $multiplier) = (@_); return Money->dollar({amount => $self->{amount} * $multiplier}); } 1; package Franc; use strict; use warnings; use base 'Money'; use overload "*" => \× sub new { my ($class, $opts) = (@_); return $class->SUPER::new($opts); } sub times { my ($self, $multiplier) = (@_); return Money->franc({amount => $self->{amount} * $multiplier}); } 1;
t/00money.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 = Money->dollar({amount => 5}); is($five * 2, Money->dollar({amount => 10})); is($five * 3, Money->dollar({amount => 15})); } sub test_equality : Test(5) { ok(Money->dollar({amount => 5}) == Money->dollar({amount => 5})); ok(Money->dollar({amount => 5}) != Money->dollar({amount => 6})); ok(Money->franc ({amount => 5}) == Money->franc ({amount => 5})); ok(Money->franc ({amount => 5}) != Money->franc ({amount => 6})); ok(Money->franc ({amount => 5}) != Money->dollar({amount => 5})); } sub test_franc_multiplication : Test(2) { my $five = Money->franc({amount => 5}); is($five * 2, Money->franc({amount => 10})); is($five * 3, Money->franc({amount => 15})); } sub test_currency : Test(2) { is(Money->dollar({amount => 1})->currency, 'USD'); is(Money->franc ({amount => 1})->currency, 'CHF'); } 1;