Commit | Line | Data |
ddc8edba |
1 | #!/usr/bin/perl |
2 | |
3 | use strict; |
4 | use warnings; |
5 | |
6 | use Test::More no_plan => 53; |
7 | use Test::Exception; |
8 | |
9 | BEGIN { |
10 | use_ok('Class::MOP'); |
11 | } |
12 | |
13 | { |
14 | package BankAccount; |
15 | |
16 | use strict; |
17 | use warnings; |
18 | use metaclass; |
19 | |
20 | use Carp 'confess'; |
21 | |
22 | BankAccount->meta->add_attribute('$:balance' => ( |
23 | accessor => 'balance', |
24 | init_arg => 'balance', |
25 | default => 0 |
26 | )); |
27 | |
28 | sub new { (shift)->meta->new_object(@_) } |
29 | |
30 | sub deposit { |
31 | my ($self, $amount) = @_; |
32 | #warn "deposited $amount in $self"; |
33 | $self->balance($self->balance + $amount); |
34 | } |
35 | |
36 | sub withdraw { |
a4258ffd |
37 | my ($self, $amount) = @_; |
38 | my $current_balance = $self->balance(); |
39 | ($current_balance >= $amount) |
ddc8edba |
40 | || confess "Account overdrawn"; |
41 | #warn "withdrew $amount from $self"; |
42 | $self->balance($current_balance - $amount); |
43 | } |
44 | |
45 | package CheckingAccount; |
46 | |
47 | use strict; |
48 | use warnings; |
49 | |
50 | use base 'BankAccount'; |
51 | |
52 | CheckingAccount->meta->add_attribute('$:overdraft_account' => ( |
53 | accessor => 'overdraft_account', |
54 | init_arg => 'overdraft', |
55 | )); |
56 | |
a4258ffd |
57 | CheckingAccount->meta->add_before_method_modifier('withdraw' => sub { |
ddc8edba |
58 | my ($self, $amount) = @_; |
59 | #warn "hello from before"; |
60 | my $overdraft_amount = $amount - $self->balance(); |
61 | if ($overdraft_amount > 0) { |
62 | #warn "overdrawn $overdraft_amount"; |
63 | $self->overdraft_account->withdraw($overdraft_amount); |
64 | $self->deposit($overdraft_amount); |
65 | } |
66 | #warn "balance after overdraft : " . $self->balance; |
67 | }); |
68 | |
69 | ::ok(CheckingAccount->meta->has_method('withdraw'), '... checking account now has a withdraw method'); |
70 | } |
71 | |
72 | |
73 | my $savings_account = BankAccount->new(balance => 250); |
74 | isa_ok($savings_account, 'BankAccount'); |
75 | |
76 | is($savings_account->balance, 250, '... got the right savings balance'); |
77 | lives_ok { |
78 | $savings_account->withdraw(50); |
79 | } '... withdrew from savings successfully'; |
80 | is($savings_account->balance, 200, '... got the right savings balance after withdrawl'); |
81 | |
82 | $savings_account->deposit(150); |
83 | is($savings_account->balance, 350, '... got the right savings balance after deposit'); |
84 | |
85 | my $checking_account = CheckingAccount->new( |
86 | balance => 100, |
87 | overdraft => $savings_account |
88 | ); |
89 | isa_ok($checking_account, 'CheckingAccount'); |
90 | isa_ok($checking_account, 'BankAccount'); |
91 | |
92 | is($checking_account->overdraft_account, $savings_account, '... got the right overdraft account'); |
93 | |
94 | is($checking_account->balance, 100, '... got the right checkings balance'); |
95 | |
96 | lives_ok { |
97 | $checking_account->withdraw(200); |
98 | } '... withdrew from checking successfully'; |
99 | |
100 | is($checking_account->balance, 0, '... got the right checkings balance after withdrawl'); |
101 | is($savings_account->balance, 250, '... got the right savings balance after overdraft withdrawl'); |
102 | |