Imagine for a moment that you're writing the billing
component of an online store. Now, there are several
ways a customer can pay: they can use a credit card, a
debit card, a check, etc. You could use a switch
statement (or an if/elsif chain in Perl 5) to do it:
given ($payment_method) { # All code samples are Perl 6
when 'credit' { do_credit_card($num, $exp) }
when 'debit' { do_debit_card($num, $exp) }
when 'check' { do_check() }
default { die }
}
But maybe there are several steps involved--early in
the process you have to authorize, then later you have
to execute the transaction, and perhaps you need to
store the info in a database so crackers can steal it.
That requires three switch statements in different
areas of the code. And then six months down the road,
you want to add PayPal support, so you have to change
three different switch statements, but in one of them
you accidentally put 'payapl', but it's already gone
into production so the company loses five thousand
dollars and fires you.
You don't want to get fired.
So instead, you write an object to represent a
payment method, and a subclass for each specific way of
paying:
class MyStore::PayMethod {
# A submethod is a method that isn't inherited.
submethod new { die "Create a subclass, silly." }
method authorize($price) { ... }
method execute($price) { ... }
method store($dbh) { ... }
}
class MyStore::PayMethod::CreditCard is MyStore::PayMethod {
# Colon means private--only code in this class can see
# it.
has ($:ccnum, $:ccexp, $:ccname);
submethod BUILD($:ccname, $:ccnum, $:ccexp) {}
method authorize($price) { (code to authorize) }
method execute($price) { (code to execute) }
method store($dbh) { (code to store) }
}
Now you can create the appropriate object exactly once:
my $class;
given($payment_method) {
when 'credit' { $class=MyStore::PayMethod::CreditCard }
when 'debit' { $class=MyStore::PayMethod::DebitCard }
when 'check' { $class=MyStore::PayMethod::Check }
}
my $payobj=$class.new(*%params);
And then later on, when it's time to authorize, all you
need to do is put the statement
$payobj.authorize()--no nasty switch
required.
In essence, an object is a way to make tasks with
different data look the same to the outside world, even
if the exact algorithm used to do that task to that
data is radically different. It's a little like
passing around a table of functions, only cleverer.
Edit: a friendly elder reminded me
that has requires parens when declaring
multiple attributes, just like my and
our in Perl 5.
=cut
--Brent Dax
There is no sig.
|