Contents 1. Review of References 2. Subroutines and Modules 3. Overview of Perl OO 4. Constructors and Destructors 5. Inheritance and Overloading 6. Encapsulation 1 Review of References What are references? Creating references Using references Dereferencing array and hash references Examining references 2 What are references? A Reference refers to the memory occupied by data • Not the variable name, but the value Perl References are like Java References References are not like pointers in C/C++ • Are memory-safe • No pointer arithmetic Use of References • Pass arrays and hashes to subroutines • Pass values by reference • Build complex data structures • Implement objects • Support aliases 3 Creating references A reference is a scalar variable Created using the unary operator \ From existing variable or subroutine: $scalarref $hashref $arrayref $subref $retnvalref = = = = = \$scalar; \%hash; \@array; \&subroutine; \subroutine(); Anonymously: $hashref = { key1 => val1, key2 => val2 }; $arrayref = [qw(This is a list) ]; $subref = sub { print "I have no name\n" } 4 Using references Prefix value with character indicating type • Prefixes run from right to left • Run-time type checks $a = \ 'Hello'; $b = $$a; print "A: $a; B: $b; A-ref: $$a\n"; $c = [1, 2, 3]; @d = @$c; print "C: $c; D: @d; C-ref: @$c\n"; $e = {first => 'Peter', last => 'Jones'}; %f = %$e; print "E: $e; F: ", %f, "\n"; A: SCALAR(0x176566c); B: Hello; A-ref: Hello $rr = \$a; C: ARRAY(0x176f0d8); D: 1 2 3; C-ref: 1 2 3 print "\$rr: $rr $$$rr\n"; E: HASH(0x176f1bc); F: lastJonesfirstPeter $rr: REF(0x1765660) Hello SCALAR prior to v.5.8 5 Dereferencing array and hash references Use ->{} and ->[] for clarity • After the first ->, extra [] and {} are allowed without -> @nums = qw(zero one two three four); $numref = \@nums; print "At 2: $numref->[2]\n"; $hashref = {UK => 'London', Ireland => 'Dublin', France => 'Paris', Germany => 'Berlin', Spain => 'Madrid', Italy => 'Rome'}; print "Spain: $hashref->{Spain}\n"; $tricky = [ { key1 => 'value1' }, { key2 => 'value2' } ]; print "$tricky->[0]{key1}\n"; At 2: two Spain: Madrid value1 6 Examining references Is a scalar value a reference? If so, what type? Use the ref function • Different behaviour for objects $x = "Hollow World"; if (!ref($x)) { print "\$x is not a ref!\n" } $a = [ 1, 2, 3 ]; $b = \'Name'; $c = { 'Name' => 'John' }; $r = \$c; returns an empty string if not a reference $x is not a ref! ARRAY;SCALAR;HASH;REF print ref($a), ';', ref($b), ';', ref($c), ';', ref($r), "\n"; 7 Summary References refer to a glob of data • or referent Created using: \prefix [ ] anonymous array composer { } anonymous hash composer Dereferenced using: • Type prefix $$scalarref, @$arrayref, %$hashref • $arrayref->[index] • $hashref->{key} 8 Subroutines and Modules Calling a subroutine Named and default parameters References to subroutines Module loading: %INC, @INC and use lib Namespaces Multiple packages per module 9 Calling a subroutine There are several ways to call a subroutine: subroutine (parameter list); &subroutine; Just plain weird! & passes @_ as the default parameter sub blue { return ('one', @_) } sub red { &blue The current value of @_ is passed, not an empty list } print red(qw(The quick brown fox)),"\n"; print blue(),"\n"; oneThequickbrownfox one 10 Named and default parameters Pass a hash to a subroutine • Can be merged with default arguments • Keys may have a leading dash (Tk, CGI) my %dft = (Year => 1970, Month => 1, Day => 1); sub make_date { my %args = (%dft, @_); if (keys %args != keys %dft) { die "Invalid arguments: @_\n" } return "$args{Month}-$args{Day}-$args{Year}"; } print make_date(), "\n"; print make_date(Year => 2000), "\n"; print make_date(Month => 10, Day => 31), "\n"; 1-1-1970 1-1-2000 10-31-1970 11 References to subroutines May be created using the \ operator: sub oscar { print "This is oscar\n" } my $ref = \&oscar; print "\$ref: $ref\n"; &$ref(); $ref->(); prototypes are ignored Don't supply ( )! that would call the subroutine Alternative syntax Or by creating an anonymous subroutine: • To create a private subroutine, qualify with my: my $sref = sub { print "This has no name\n" }; &$sref(); $sref->(); Don't forget the semi-colon 12 The library directories use searches the directories in the @INC array • Defined when perl was built and installed • Includes current working directory The modules already loaded are listed in %INC hash • Module names are keys, full pathnames values The search list may be changed • With -I command-line option to perl • With environment variables PERL5LIB or PERLLIB • With use lib use lib '/usr/lib/perl-stuff/shared-modules'; use lib $ENV{MY_PERL_LIB}; use MyModule; 13 Namespaces Each module has its own namespace. • All subroutines and variables names are local to that module • Symbols are exposed by the export mechanism – A symbol is a global variable or subroutine Implemented by prefixing the package name • For example: ToFromJpeg::foo If no prefix is specified • Current package name is assumed By specifying a prefix • Access another module's variables and subroutines The main program has main:: prefixed implicitly • main::X has the same meaning as ::X 14 Multiple packages per module A module file can contain multiple packages • Each package has its own namespace • Module can have a private helper package However: • use takes a module name • Symbol import only works for module name • The scope of my variables is file-wide, not package-wide Examples follow… 15 Multiple packages per module - 1 use strict; package Foo; my $name = 'initial value'; sub get { return $name; } Packages share ‘my’ variable package Bar; sub set { ($name) = @_; } sub get2 { return $name; } 1; use Foo; print "(1) ", Foo::get(), "\n"; Bar::set('new value'); print "(2) ", Foo::get(), "\n"; 16 Multiple packages per module - 2 { package Foo2; my $name = "Initial Value"; sub get { return $name; } Packages are independent } { package Bar2; sub set { ($name) = @_; } sub get2 { return $name; } } 1; fails with use strict use Foo2; print "(1) ", Foo2::get(), "\n"; Bar2::set('new value'); print "(2) ", Foo2::get(), "\n"; 17 Summary &sub passes @_ by default Named and default parameters are emulated with a hash Packages are defined with package class = namespace = package <= module Modules are used using use There may be more than one package in a module 18 Overview of Perl OO Review of OOOP Basic object usage Implementing objects Accessing object fields Constructors Implementing object methods Method calls Summary 19 Review of Object Oriented Programming Some OO terms: • Objects – Anything that provides a way to access, process and modify data. • Class – Is a description of the type of object • Method – The means by which an object can be accessed, processed or modified. • Inheritance – Allows existing objects to build on other classes to provide additional data or methods. • Polymorphism – Allows an object to behave differently depending on the class it belongs to • Encapsulation – Separates interface from implementation, with publicly accessible behaviour and a privately maintained state 20 Basic object usage Classes are stored in module files • Loaded with the use command Use new to create an object Use -> for method calls use Document; use Fax; my $doc = new Document('REPORT.DOC'); my $fax = new Fax('Travel Fax', '+31 70 364789'); $doc->set_header('Report on Perl Objects'); $doc->print('PostScript', 'A4'); Method calls on Document object $fax->send(); Method call on Fax object 21 Objects are references Objects are implemented using references • No new data types have been introduced • Internally, objects can be hashes, arrays or scalars • The ref function shows the class of the object use Document; use Fax; my $doc = new Document('REPORT.DOC'); my $fax = new Fax('Travel Fax', '+31 70 364789'); print "Doc: $doc\n"; print "Fax: $fax\n"; print "Ref of doc: ", ref($doc), "; Ref of fax: ", ref($fax), "\n"; Doc: Document=HASH(0x80b4870) Fax: Fax=HASH(0x80b9cdc) Ref of doc: Document; Ref of fax: Fax 22 Implementing Objects Classes are implemented using packages • Each class in a separate file Decide on a data-type • Hash, array or scalar Define the methods • Implemented using subroutines use NumberList; my $odd = new NumberList(1,3,5,7,9); my $dozen = new NumberList(1..12); print "Sum of odd: ", $odd->sum(), "\n"; print "Average of dozen: ", $dozen->average, "\n"; Sum of odd: 25 Average of dozen: 6.5 23 Accessing object fields Perl classes often do not restrict access to member data • No privacy • Small-town v.s big-city mentality use NumberList; my $odd = new NumberList(1,3,5,7,9); print "(1) Sum of odd: ", $odd->sum(), "\n"; $odd->[0] = 100; print "(2) Sum of odd: ", $odd->sum(), "\n"; Don't use this Good practice suggests the use of access methods use NumberList; my $odd = new NumberList2(1,3,5,7,9); print "(1) Sum of odd: ", $odd->sum(), "\n"; $odd->set_element(0, 100); print "(2) Sum of odd: ", $odd->sum(), "\n"; Use this instead 24 Constructors In C++ and Java • A constructor always has the name of the class • Is invoked from new In Perl • Any subroutine may be a constructor • It is usually called new • new is not a built-in language construct A Perl constructor usually returns a reference • But may return a non-object, or undef to indicate failure The magic is performed by the bless command 25 Implementing object methods - details Any package subroutine is also a method Methods may be called using one of three ways • Object + method name (object method, with inheritance) • Class + method name (class method, with inheritance) • Full package::subroutine name (direct, no inheritance) Each way has its use • Object method used most of the time • Class method used for constructors, initialisers • Direct method used to override inheritance 26 Method calls Object method call • Passes the object used, not the class name • Not subject to prototype checks $object->method (argument-list) method $object (argument-list) Class method call • Passes the class name, not the object • Not subject to prototype checks $class->method (argument-list) method $class (argument-list) Direct method call • Avoids inheritance class::method (argument-list) • Does not require an object instance • Subject to prototype checks 27 Implementing object methods: example package Example; sub new { return bless {} } sub direct_call { ... } Constructor returning a blessed reference to an empty hash 'Normal' subroutine with arguments in @_ sub class_call { print "Class call, Args: @_\n"; my $class = shift; } First argument passed is the class name sub object_call { print "Object call, Args: @_\n"; my $this = shift; } First argument passed is a reference to the object 1; 28 Implementing object methods: example Object Call First argument passed is a reference to the object use Example; $e = new Example; $e->object_call('one', 'two'); object_call $e ('three', 'four'); Object. No of args:3 Args: Example=HASH(0x804c8d4) one two Object. No of args:3 Args: Example=HASH(0x804c8d4) three four Class Call First argument passed is the class name use Example; $e = new Example; class_call Example('one', 'two'); Example->class_call('three', 'four'); Class. No of args:3 Args: Example one two Class. No of args:3 Args: Example three four 29 Summary Perl provides some OOP features A module represents a class An object is a referent new is an ordinary subroutine • Called with an alternative syntax • bless does the real work 30 Constructors and Destructors Object constructors Object destructors Reference counting Object data types Named constructors Virtual constructors Singletons 31 Object constructors Constructor • Allocates memory • Initializes object • Invokes ‘bless’ to create thr object • Base class constructor is not called automatically! sub new { my ($class, $file) = @_; my $this = { '_file' => $file }; bless $this, $class; return $this; } Use the two argument version of bless to allow constructor inheritance 32 Object destructors Destructor • Invoked when object is destroyed • Invocation time not guaranteed • Can clean up resources • Often not necessary • Base class destructor is not called automatically! LogFile destructor sub DESTROY { my ($this) = @_; my $fh = $this->{'fh'}; print $fh "$0: Closing logfile at " . scalar(localtime) . "\n"; $fh->close(); } 33 Reference counting Perl 5 doesn’t have full garbage collection • Reference counting is used instead • Circular references could lead to memory leaks • Two-phase destruction releases all memory at program end use Person; print "Start of main program\n"; foo(); print "End of main program\n"; sub foo { my $romeo = new Person('Romeo', 'Montague', 17); my $juliet = new Person('Juliet', 'Capulet', 13); my $zaphod = new Person('Zaphod', 'Beeblebrox', 123); $romeo->set_partner($juliet); $juliet->set_partner($romeo); } Start of main program Zaphod is destroyed... farewell! End of main program Juliet is destroyed... farewell! Romeo is destroyed... farewell! 34 Object data types Objects can be of any type • Scalar - useful for "inside-out" objects • Array - small memory footprint • Hash - easy to use, and most popular Pseudo-Hashes seemed a good idea at the time… • Also known as hash-arrays • Inefficient, slow, and difficult to debug • Deprecated at 5.8, removed from Perl at 5.10 $fred = [ { first => 1, last => 2}, 'Fred', 'Bloggs' ]; print "Info: $fred->{'first'} $fred->{'last'}\n"; print "Keys: ", keys %$fred, "\n"; while (my ($key, $val) = each %$fred) { print "$key\t$val\n"; } Hash-Array example 35 Named constructors Constructor need not be called ‘new’ • But it is a good idea if you only have one • Multiple named constructors are allowed Preferred use Account; my $cr = Account->make_credit_account(); my $db = Account->make_debit_account(); use Account; Same effect, different ways of calling a class method my $cr = make_credit_account Account(); my $db = make_debit_account Account(); use Image; my $one = gif Image("test.gif"); my $two = jpeg Image("morgan.jpg"); 36 Virtual constructors Design pattern to simplify client code • Many related classes • Client doesn’t known and care about details • Code must remain extensible • Features can be specified per application Image GIF Image JPG Image PNG Image # Client code use Image; my $img = new Image('data.jpg'); 37 Virtual constructors Exemplars Exemplar classes Store object of each exemplar class in an array use Base class use Register the exemplar class "User" written main Registry module use 38 Virtual constructors - exemplar registry Register example objects with base class • Objects may be fake • Registry may be different per application • Needs to include the sub classes that are exemplars package ImageRegistry; use use use use Image::GIF; Image::Jpeg; Image::PNG; Image; Load each "exemplar" class Create a dummy blessed reference for each exemplar class BEGIN { foreach my $class (qw(Image::GIF Image::Jpeg Image::PNG)) { Image->register(bless \do{my $anon}, $class); } } 39 Virtual constructors - base class Base class walks the exemplar chain to create objects package Image; my @exemplars; Called by the Registry module sub register { my ($class, $obj) = @_; push @exemplars, $obj; } sub new { my ($class, $filename) = @_; foreach my $obj (@exemplars) { my $exp_class = ref($obj); my $this = $exp_class->new($filename); return $this if defined $this; } return; } 1; Base class constructor is called by the User code my $obj = Image->new($filename); 40 Singletons Singleton: only one instance of an object exists • Object-oriented alternative to global variables • Object can have any method you want package Singleton; my $instance; sub new { my ($class) = @_; $instance ||= bless {}, $class; return $instance; } The Orcish manoeuvre sub method { … } 1; 41 Summary Constructor magic is: bless $this, $class Destructor is named DESTROY Object data type can be any valid Perl type • More exotic types have been tried @ISA or use base to indicate base classes Base class methods may be called using SUPER:: All classes are derived from UNIVERSAL 42 Inheritance and Overloading Method inheritance Constructor inheritance Multiple inheritance order SUPER class UNIVERSAL class Operator Overloading 43 Method inheritance Defined by the @ISA array or use base pragma package Fax; use strict; use Document; BEGIN { our @ISA = ('Document'); } ... 1; or package Fax; use strict; use base 'Document'; ... 1; Preferred Call parent class methods using SUPER • Use object or class call • Both examples call Document::pmethod subroutine sub cmethod { my $self = shift; $self->SUPER::pmethod(); } sub cmethod { Fax->SUPER::pmethod(); } 44 Constructor inheritance Constructors can be inherited • Always use the two argument version of bless sub new { my ($class, %args) = @_; Method in ‘Base’ class my $this = \%args; bless $this, $class; return $this; } sub clone { my ($class) = @_; $class = ref($class) if ref($class); Clone an object my $this = bless {}, $class; return $this; } Allow a class name or an object to be used 45 Multiple inheritance order Class hierarchy Document 3 Fax @ISA=('Document') 2 Report @ISA=('Document') Letter @ISA=('Document') 4 FaxedReport @ISA=('Fax', 'Report') 1 46 SUPER class - which one? package FaxedReport; use Fax; use Report; SUPER uses whichever base class method it finds first our @ISA = qw (Fax Report); sub foo { return SUPER::foo(@_); } 1; $FxRt = new FaxedReport (); print '$FxRt isa :'. ref ($FxRt) . "\n"; $retn = $FxRt->foo(); print "<$retn>\n"; $FxRt isa :Fax <Fax foo> 47 UNIVERSAL class Implicit parent class of all objects • Allows ‘is this a’ or ‘does this support’ calls use Document; use Fax; my $doc = new Document; my $fax = new Fax; Fax doc Fax Fax Fax is-a Document: yes is an array: no supports foo: yes supports bar: yes supports bogus: no print "Fax is-a Document: ", ($fax->isa('Document') ? "yes" : "no"), "\n"; print "doc is an array: " . (UNIVERSAL::isa($doc, 'ARRAY') ? "yes" : "no"), "\n"; foreach my $method (qw(foo bar bogus)) { print "Fax supports $method: " . ($fax->can($method) ? "yes" : "no"), "\n"; } 48 Operator overloading Re-define the operators for a class • Your method will be called instead of the built-in version • May be inherited • Objects are truly integrated with built-in types • Uses the ‘overload’ pragmatic module – For a list of operators, see perldoc overload – or %overload::ops User written subroutines package Complex; use overload ('cmp' '<=>' '""' '-' '+' => => => => => 'compare', 'compare', 'as_string', 'subtract', 'add'); ... 49 Operator overloading - the details 1 Many methods provided mathemagically • += and ++ are provided if you have + • Precedence and associativity remain the same package Complex; sub add { my ($lhs, $rhs, $swapped) = @_; my ($self, $add); if ($swapped) { $self = $rhs; $add = $lhs; } else { $self = $lhs; $add = $rhs; } $one = new Complex(1, 2); print $one + 1; print 5 - $one; Calls Complex::add($one, 1, false) Calls Complex::add(1, $one, true) 50 Operator overloading - the details 2 Magic autogeneration may be suppressed with: use overload 'fallback' => 0; Not all operators may be overloaded • -> and () may not be overloaded • Copy constructor = is called during operations like ++ and += – It does not overload the assignment operator – Not normally needed • 'nomethod' may be assigned for operators not overloaded – Uses a subroutine with 4 arguments, 4th is the operator invoked Test to see if overloading is being used if (overload::Oveloaded $obj) {…} if (overload::Method ($obj, '+')) {…} 51 Summary @ISA or use base to indicate base classes Base class methods may be called using SUPER:: All classes are derived from UNIVERSAL Most basic operators may be overloaded 52 Encapsulation Defining an object The fields pragma and strong typing Encapsulation? Inside-out objects Access methods 53 Defining object layout Objects can be implemented using any data type • Normally, not strongly typed • Hash leads to best-looking code • Array use least amount of memory You can define a fixed object layout • Checked at compile time • Sub-classes inherit parent fields • Fields can be private to a class • Implemented by ‘fields’ and ‘base’ modules You can define "inside-out" objects • Where the object address is the key to an internal hash • Provides encapsulation 54 The fields pragma Define fields used by your object Prior to 5.9, uses a pseudo hash • Pseudo-hashes are removed at 5.10 Post 5.9, uses a restricted hash • Better performance than a pseudo hash • Still no mandatory security • Hash is locked using lock_keys() and lock_values() • May be overridden using Hash::Util methods my classname ($var1, $var2, …) No longer recommended • But may be present in 'legacy' applications 55 Implementing methods with strong typing When strong typing is used… • It must be used everywhere, or have a ‘traditional’ hash-array package Dude; use base 'Person'; use fields qw(editor beer); sub new { my $class = shift @_; # Intended my $this = $class->SUPER::new(@_); bless $this; $this->[0] = \do{my %FIELDS}; $this->{'drink'} = pop @_; $this->{'editor'} = pop @_; return $this; } # method in package Dude sub display { my Dude $this = shift @_; print "$this->{first} drinks $this->{drink}\n"; } 56 Perl encapsulation? Encapsulation using a hash is not straightforward • Security is voluntary – Also a problem with "Restricted Hashes" Hash::Util • Attribute names are symbolic (text) • Child classes can impose structure on the parent Code can access the underlying structures • Class cannot be changed without breaking code • Then whose fault is it? use Dude; my $Larry = new Dude('Larry', 'Wall', 33, 'vi', 'Guinness'); # Let's break some rules print "$Larry->{age}\n"; $Larry->{drink} = 'Carrot juice'; Should use methods to do this. Calling it bad practice does not prevent it ! 57 Inside-out objects Uses object's address as the key to internal hashes package Person; use strict; use Scalar::Util qw(refaddr); { my %first; # First names my %last; # Last names my %age; # Person's age Attributes are clearly defined sub new { my ($class, $first, $last, $age) = @_; my $this = bless \do{my $some_scalar}, $class; my $key = refaddr $this; $first{$key} = $first; $last {$key} = $last; $age {$key} = $age; return $this; } } 1; Get any old (unique) reference Extract the address from the reference 58 Inside-out objects The object is meaningless outside the class • It is a reference to a scalar which is undef • It is used as a key to the lexical attribute hashes This means the implementation is hidden • Keys of an object's hash are no longer exposed • Attributes cannot be added or removed from the object Access is fast and efficient • Simple to implement and debug # Let's break some rules print "$Larry->{age}\n"; $Larry->{drink} = 'Carrot juice'; Not a HASH reference at Dude1.pl line 12. 59 Inside-out object destructors Always provide a destructor for inside-out objects • Only the key will drop out of scope - not the value package Dude; use base 'Person'; ... { my %drink; my %editor; ... sub DESTROY { my ($this) = @_; my $key = refaddr $this; package Person; ... { my %first; # First names my %last; # Last names my %age; # Person's age ... sub DESTROY { my ($this) = @_; my $key = refaddr $this; $this->SUPER::DESTROY(); delete $first {$key}; delete $last {$key}; delete $age {$key}; delete $editor{$key}; delete $drink {$key}; } } } } 60 Access method: shared or separate? There are two schools of thought • Provide a single read and write accessor sub speed { my ($self, $speed) = @_; $self->{speed} = $speed if (defined $speed); return $self->{speed}; } • Provide separate accessors sub get_speed { my ($self) = @_; return $self->{speed}; } sub set_speed { my ($self, $speed) = @_; $self->{speed} = $speed; return $self; } 61 Access method: shared or separate? Provide general purpose accessors? sub get { my ($this, $attr) = @_; return $this->{attr}; } sub set { my ($this, $attr, $value) = @_; $this->{$attr} = $value; return $this; } 62 Inside-out accessors my (%speed, %reg, %owner, %mileage); my %hashrefs = ( speed => \%speed, reg => \%reg, owner => \%owner, mileage => \%mileage); sub set { my ($self, $attr, $value) = @_; my $key = refaddr $self; if ( !exists $hashrefs{$attr} ) { carp "Invalid attribute name $attr"; } else { $hashrefs{$attr}{$key} = $value; } } A 'get' would be similar $car->set ('speed', 30); 63 Summary The ‘fields’ pragma is not recommended • Prior to 5.10, uses a deprecated structure • MUST remember to use strong typing Inside-out objects are recommended • Attributes are hidden in lexical hashes • No risk of hash key collisions • MUST remember to supply a destructor Give some thought to accessors • Shared or separate? • Generic inside-out accessors? 64 The Way Ahead Useful modules Recommended books What have we achieved? What next? 65 Useful modules Class::Struct • Auto-generates a class as a struct-like datatype (Base) Class::MethodMaker • Method generation (CPAN) Class::Std • Support for inside-out objects (CPAN) Moose • Another approach to building Perl classes (CPAN) Object::InsideOut • Comprehensive support for implementing classes using inside-out objects Storable • A way of making data types persistent (Base) FreezeThaw • Stringifies an object suitable for dumping to a file (CPAN) 66 Recommended books Programming Perl (3rd edition, July 2000) • Larry Wall, Tom Christiansen, Jon Orwant, ISBN 0-59600-027-8 Perl Pocket Reference (4th edition, July 2002) • Johan Vromans, ISBN 0-596-00374-9 Perl Cookbook (2nd edition September 2003) • Nathan Torkington and Tom Christiansen, ISBN 0-596-00313-7 Effective Perl Programming (Addison-Wesley 1998 ) • Joseph Hall and Randal Schwartz, ISBN 0-20141-975-0 Object Oriented Perl (Manning 2000) • Damian Conway ISBN: 1-884777-79-1 Perl Best Practices (July 2005) • Damian Conway ISBN: 0-596-00173-8 67 What next? QA Course material Consolidate existing knowledge Practical experience Support 68 And then? Perl 6 for Perl 5 Programmers (TBA) Win32 Programming Essentials Unix Programming Develop knowledge and skills in Perl and related areas Java 69 How? Books and magazines Interest groups and discussions with colleagues Perl APIs OO Web Further information in the course material Appendices Online information and resources Further courses Very Small class nonsense { public: // sector ... private: // parts ... }; The PARTS Catalogue is the main source of Parts for y our application. The Catalog resembles a notebook control containing pages that can be accessed through the use of the tabs. There are both major and minor tabs. The major tabs are located along the right-hand side, and the minor tabs can be seen along the bottom edge. The minor tabs indicate that there are more pages for that particular major tab; there are different minor tabs for each major tab. Another way of turning through the pages, is to use the page control buttons. Notice that the page numbers change when y ou move between pages. On the next slide, y ou will become more familiar with the Workbench, where y ou will see there is an information area which can contain brief help and comments. This will become apparent when y ou move the mouse over various Parts in the Catalog - the information area of the Workbench will display a short description about that Part. It is also worth noting that moving the mouse over the background area of the Catalog page will give y ou a description of that page. This default Catalog is held as a file, with a .CAT extension in the sub-directory SYSTEM of y our install directory . For example, C:\PARTS\SYSTEM\PARTS.CAT Later in the course we shall see how to customize the Catalog, and how to create new ones. The File menu button will be used to load other catalog files. QA And Small Again class nonsense { public: // sector ... private: // parts ... }; PARTS enables developers to work more closely with end users to build the user interface components, which can be dynamically changed as the user requirements evolve. The construction of applications from smaller components enables the developer to reuse much of the code that they have already written elsewhere, thus reducing development time, as well as the potential for introducing coding errors. PARTS also gives the developer the ability to make use of existing 3GL code (C or C++, for example) code that is packaged as a DLL. More experienced developers can benefit from Smalltalk/V, either as a complete programming language, or as a scripting language to build further functionality into the application. On the other hand, less-experienced users can become productive very quickly. This is because PARTS is able to abstract the user from the underlying code. 70 In closing... Please complete your course evaluation form and hand it to the instructor Thank you and well done! 71