Upload
others
View
3
Download
0
Embed Size (px)
Citation preview
Object-Oriented-Programming !(OOP)
Basically it’s all about abstraction & information hiding
n Good programs consist of layer upon layer of reusable code (think of software tools).
n The programmer should be free to tinker with the internal workings of a set of software tools, but with little risk of breaking programs that use the tools.
n This is accomplished by introducing layers of abstraction. Good programmers have been doing this since the beginning of programming. There are many ways of doing this.
n In object oriented programming, bundled sets of data and code are initialized and then passed around and used within the program. Data within objects is never accessed directly. It is only accessed via code in the objects.
Review of subroutine basicsn Calling a subroutine
n Declaring a subroutine
n Not restricted to returning lists, can return hashes or other objects
(...output_list...) = foo(...input_list...)
sub foo {
(...input_list...) = @_;
... Perl statements ...return (...output_list...)
}
Review of reference basicsn References point to “stuff” in memory
n Recover “stuff” with “dereference operator” ( -> )
$anonArray = [...list of values...];$anonHash = {...list of key/value pairs...};
$anonSubroutine = sub {...Perl statements ..};
value = $anonArray->[index]
value = $anonHash->{key}
(...output_list...) = $anonSubroutine->(...input_list...)
demo #1#!/usr/bin/perluse warnings;use strict;
my $anonArray = [1,2,3,4,"five"];my $anonHash = { "pi" => 3.14159, "e" => 2.71828, "c" => 2.99792458 };my $anonFunc = sub {
print "hello world\n";};
print $anonArray->[4],"\n";print $anonHash->{"pi"},"\n";$anonFunc->();
demo: references3.pl
demo #2
#!/usr/bin/perluse warnings;use strict;
my $anonHash = { hello => sub { print "hello world\n"}, bye => sub { print "goodbye cold cruel world\n"} whatever => sub { print ”$_[0]\n"}};
$anonHash->{hello}();$anonHash->{bye}();$anonHash->{whatever}(“any text”);
An anonymous hash containing anonymous functions
demo: references4.pl
back to OOPn Many useful library modules (e.g. bioperl) are written using an
object-oriented programming style
n Using Objected oriented modules is easy
n Writing Object oriented moduels is a little harder than using them, !but easier than writing traditional modules
n Key concepts:n information hiding
n data is hidden from the calling routines n Encapsulation
n Data and functions encapsulated into one object. Data manipulated by functions not directoy.
n Abstractionn Hierarchies of subroutines & functions, each hides the details of it’s
data and implementation from calling routines
Perl Objects n Perl extends the capabilities of packages and modules to
automatically build objects for you and to hide some of the messy details.
n OOP terminology (translated into perl)n Object -- a hash reference whose values are !
references to data and subroutinesn Method -- A subroutine incorporated in an objectn Class -- a package that declares objects and references
bless() distinguishes an ordinary hash from an “object”
n Perl needs to know which hash references are objects so that it knows to treat them a little bit differently.
n Bless() attaches a tag to a hash referencen Existence of a tag tells perl to treat a hash reference as an
objectn The tag is just a string which is the name of the package
where the reference (the referent) was declaredpackage demoPackage;
my %someHash;my $s = \%someHash;print ”hash references is: $s\n";
bless($s);print ”blessed reference is: $s\n";
demo: bless1.pl
What does bless() really do to a hash reference?
n Marks the hash with a tag that is the package name where the bless is applied
n Automatically adds hash entries corresponding to globals in the package: n A key for each global perl identifiern The value is a reference to the corresponding data or
functions
creating an object with new() & bless()
my $s = demoPackage::new(); # create an objectprint “$s\n”; # print the reference$s->test("foo", "goo"); # invoke a method
# ---------the package starts here---------package demoPackage;
sub new { return bless {}} # bless on an empty hash
# print each element of the argument listsub test { foreach (@_) { print "$_\n"; }}
demo: bless2.pl
Huh! Why is there an extra element in @_ ?
n Recall that:n A method, is just a subroutine that is invoked by dereferencing a
function reference, in a blessed hash.n A class, is just a package.n An object, is just a blessed hash.
n When invoking a method in an object, Perl automatically adds a reference-to-the-object itself, to the beginning of @_ .!This is so that the method can access the other data and functions in the class, if it needs to.
Example: accessing private variablesmy $s = demoPackage::new();$s->set(3.14159);$s->print_parm();
# --------- the package starts here ---------package demoPackage;our $parm;sub new { return bless {} }
sub set { my $self = shift; # shift first argument $self->parm = shift; # shift second argument}
sub print_parm { my $self = shift; print $self->parm,"\n";}
demo: bless4.pl
Writing object oriented modules
A practical example
illustrated by a sequence of examples
Working example: queues
Harry David Fernando Rosie
Dequeue (leaveQueue) Enqueue (enterQueue)
A queue consists of two things:1) A list whose items are retrieved in “First in, first out” (FIFO) order.2) A description of the queue, e.g. “ten items or less”.
How do we represent a queue?
1) The list part of the queue is represented as an array variable2) The description of the queue is represented as string variable
Queue version 1#!/usr/bin/perluse warnings;use strict;
# a queue is an array with a descriptionmy @queue=();my $description = '10 items or less';
# add customers to a queueunshift(@queue, 'Harry');unshift(@queue, 'David');unshift(@queue, 'Fernando');unshift(@queue, 'Rosie');
# checkout the customersprint "line: $description\n";while(my $who = pop @queue) {
print "checked out $who\n";}
Discussion
Problems?
1) How to handle multiple queues? Replicate the variables and replicate the code for manipulating them -- yuk!
2) The code is not ‘reusable’3) The code will be difficult to maintain. For example, when
I come back in a month to modify it, I will have to understand the implementation in order to understand what it is doing, e.g. why did I unshift and pop ?
Solve many of the problems by implementing queues as a set of subroutines.
Queue version 2
subroutines allow us to abstractaway details of the implementation.
#!/usr/bin/perluse warnings; use strict;
my $aisle1 = newQueue('10 items or less’);joinQueue($aisle1, 'Harry');joinQueue($aisle1, 'David');joinQueue($aisle1, 'Fernando');joinQueue($aisle1, 'Rosie');
print "The queue is: ". description($aisle1) . "\n";while(my $who = leaveQueue($aisle1) ) {
print "checked out $who\n";}
subroutines for Queuesub newQueue {
return { 'DESCRIPTION' => $_[0], 'QUEUE' => []
} }
sub description { return $_[0]->{'DESCRIPTION'}; }sub joinQueue { unshift(@{$_[0]->{'QUEUE'}},$_[1]); }sub leaveQueue { return pop @{$_[0]->{'QUEUE'}}; }
Perl Objects (reminder)n We will make our subroutines resusable by putting them in a module
n OOP terminology (translated into perl)n Object -- a variable containing a blessed hash reference !
which in turn contains data and subroutine ! references
n Method -- A subroutine incorporated in an objectn Class -- a package that declares objects and references
n Syntax: Instead of joinQueue($ailse1, 'Fernando');
We will write $aisle1->joinQueue('Fernando');
Queue version 3#!/usr/bin/perluse warnings; use strict;use Queue;
my $ailse1 = Queue::new('10 items or less'); $ailse1 ->joinQueue('Harry');$ailse1 ->joinQueue('David');$ailse1 ->joinQueue('Fernando');$ailse1 ->joinQueue('Rosie');
print " queue : ".$ailse1 ->description."\n";while(my $who = $ailse1 ->leaveQueue) {
print "checked out $who\n";}
package namemethod
Queue.pmpackage Queue; # package is always the first statement
sub new { return bless {
'DESCRIPTION' => $_[0],'QUEUE' => []
} }
sub description { return $_[0]->{'DESCRIPTION'}; }sub joinQueue { unshift(@{$_[0]->{'QUEUE'}},$_[1]); }sub leaveQueue { return pop @{$_[0]->{'QUEUE'}}; }
1; # 1 is always the last statement
Essentially the same routines as before, but in in object oriented style andin a file Queue.pm.
Summary1. use Queue;2. my $queue = Queue::new('10 items or less'); 3. $queue->description();
1. use gives the script access to the objects in the Queue class.2. The identifier on the LHS of ‘ ->’ is a package name (a class), so
perl knows that new is a subroutine in Queue.pm which returns:1. A hash with references to the subroutines and globals in Queue.pm2. A tag with the package name, i.e. a blessed hash
3. Because the hash reference $queue was blessed, perl knows that all identifiers on the RHS of $queue-> are found in Queue.pm.
4. The parameter list of description has the class name (Queue) automatically shifted onto it, so the method can access other methods and data in the class.
Inheritance
n Objects, can inherit methods and data from other objects.
n Methods and variables in parent object are incorporated into child objects
AbstractQueue
DisneyQueue WalmartQueue JHSPHQueue
is a is a is a
Queue version 4#!/usr/bin/perluse warnings; use strict;use DisneyQueue;
my $ride1 = DisneyQueue::new(“Mr. Toad’s wild ride”);$ride1 ->joinQueue('Harry');$ride1 -> joinQueue('David');$ride1 -> joinQueue('Fernando');$ride1 -> joinQueue('Rosie');
print $ride1 ->queueLength," waiting in the ";print $ride1 ->description," queue\n";while(my $who = $ride1 ->deQueue) {
print "$who checked out\n";}
DisneyQueue.pm
package DisneyQueue;require AbstractQueue;@ISA = qw/AbstractQueue/; # ‘Is a’
use warnings;use strict;
sub queueLength {return scalar @{ $_[0]->{'QUEUE'} };
}
1;
• Same as queue.pm, but with a more sophisticated new method new can be inherited to make AbstractQueue , DisneyQueue, etc.
• The “behind the scenes” trick is that the tag is copied from the ! invocant to the new object (see “Programming Perl”).
AbstractQueue.pm
sub new {
my $invocant = shift; # either the package name, or the reference
my $className = $invocant|| ref($invocant); return bless ( {'DESCRIPTION' => $_[0],'QUEUE'=> [] }, $className );}
sub description { return $_[0]->{'DESCRIPTION'}; }sub enqueue { unshift(@{$_[0]->{'QUEUE'}},$_[1]); }sub dequeue { return pop @{$_[0]->{'QUEUE'}}; }
http://www.iinteractive.com/moose/
Moose is an extension of the Perl 5 object system. The main goal of Moose is to make Perl 5 Object Oriented programming easier, more consistent and less tedious. With Moose you can think more about what you want to do and less about the mechanics of OOP.
Moose takes care of all the messy housekeeping for you
package MyClass1;use Moose;
sub doSomething { print "hello world\n" }
1;
#!/usr/bin/perl -wuse MyClass1;
my $object = MyClass1->new(); # returns an object, i.e. a blessed Hash$object->doSomething(); # invokes the 'doSomething' method
A module
The main
What you get “automagically”
n new()n attributes, getters and accessorsn type checking (for attributes)n subclassing