http://www.perlmonks.org?node_id=443002


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

Replies are listed 'Best First'.
Re^4: Perl 6, Object Orientation and Melting Brains
by willyyam (Priest) on Mar 29, 2005 at 13:17 UTC
    Wow, thanks BrentDax, that's a very thorough answer. I'm going to have to look at your code (and look up what some of the syntax means) a bit more, but the reason behind the division of the code this way makes sense, which is a good sign. The only other thing I notice is that if I'm going to adopt Perl 6's OO syntax I'm going to spend a lot of time on the Shift key :-)
      Just so you know, BrentDax is explaining polymorphism. That is one aspect of OO programming that many people (and it seems BrentDax is one of those many) think is a killer feature. Personally, while I think polymorphism is very powerful and useful, it is the bundling of data and code (known as encapsulation) that I find more compelling. If you re-read my earlier response in that light, you will notice that's what I'm talking about. Hopefully between these two posts you will begin to understand the fundamentals of OO. :-)