in reply to Re^2: Perl 6, Object Orientation and Melting Brains
in thread Perl 6, Object Orientation and Melting Brains

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=$*%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.

--Brent Dax
There is no sig.