source: trunk/third/perl/pod/perlbot.pod @ 20075

Revision 20075, 11.4 KB checked in by zacheiss, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20074, which included commits to RCS files with non-trunk default branches.
Line 
1=head1 NAME
2
3perlbot - Bag'o Object Tricks (the BOT)
4
5=head1 DESCRIPTION
6
7The following collection of tricks and hints is intended to whet curious
8appetites about such things as the use of instance variables and the
9mechanics of object and class relationships.  The reader is encouraged to
10consult relevant textbooks for discussion of Object Oriented definitions and
11methodology.  This is not intended as a tutorial for object-oriented
12programming or as a comprehensive guide to Perl's object oriented features,
13nor should it be construed as a style guide.  If you're looking for tutorials,
14be sure to read L<perlboot>, L<perltoot>, and L<perltooc>.
15
16The Perl motto still holds:  There's more than one way to do it.
17
18=head1 OO SCALING TIPS
19
20=over 5
21
22=item 1
23
24Do not attempt to verify the type of $self.  That'll break if the class is
25inherited, when the type of $self is valid but its package isn't what you
26expect.  See rule 5.
27
28=item 2
29
30If an object-oriented (OO) or indirect-object (IO) syntax was used, then the
31object is probably the correct type and there's no need to become paranoid
32about it.  Perl isn't a paranoid language anyway.  If people subvert the OO
33or IO syntax then they probably know what they're doing and you should let
34them do it.  See rule 1.
35
36=item 3
37
38Use the two-argument form of bless().  Let a subclass use your constructor.
39See L<INHERITING A CONSTRUCTOR>.
40
41=item 4
42
43The subclass is allowed to know things about its immediate superclass, the
44superclass is allowed to know nothing about a subclass.
45
46=item 5
47
48Don't be trigger happy with inheritance.  A "using", "containing", or
49"delegation" relationship (some sort of aggregation, at least) is often more
50appropriate.  See L<OBJECT RELATIONSHIPS>, L<USING RELATIONSHIP WITH SDBM>,
51and L<"DELEGATION">.
52
53=item 6
54
55The object is the namespace.  Make package globals accessible via the
56object.  This will remove the guess work about the symbol's home package.
57See L<CLASS CONTEXT AND THE OBJECT>.
58
59=item 7
60
61IO syntax is certainly less noisy, but it is also prone to ambiguities that
62can cause difficult-to-find bugs.  Allow people to use the sure-thing OO
63syntax, even if you don't like it.
64
65=item 8
66
67Do not use function-call syntax on a method.  You're going to be bitten
68someday.  Someone might move that method into a superclass and your code
69will be broken.  On top of that you're feeding the paranoia in rule 2.
70
71=item 9
72
73Don't assume you know the home package of a method.  You're making it
74difficult for someone to override that method.  See L<THINKING OF CODE REUSE>.
75
76=back
77
78=head1 INSTANCE VARIABLES
79
80An anonymous array or anonymous hash can be used to hold instance
81variables.  Named parameters are also demonstrated.
82
83        package Foo;
84
85        sub new {
86                my $type = shift;
87                my %params = @_;
88                my $self = {};
89                $self->{'High'} = $params{'High'};
90                $self->{'Low'}  = $params{'Low'};
91                bless $self, $type;
92        }
93
94
95        package Bar;
96
97        sub new {
98                my $type = shift;
99                my %params = @_;
100                my $self = [];
101                $self->[0] = $params{'Left'};
102                $self->[1] = $params{'Right'};
103                bless $self, $type;
104        }
105
106        package main;
107
108        $a = Foo->new( 'High' => 42, 'Low' => 11 );
109        print "High=$a->{'High'}\n";
110        print "Low=$a->{'Low'}\n";
111
112        $b = Bar->new( 'Left' => 78, 'Right' => 40 );
113        print "Left=$b->[0]\n";
114        print "Right=$b->[1]\n";
115
116=head1 SCALAR INSTANCE VARIABLES
117
118An anonymous scalar can be used when only one instance variable is needed.
119
120        package Foo;
121
122        sub new {
123                my $type = shift;
124                my $self;
125                $self = shift;
126                bless \$self, $type;
127        }
128
129        package main;
130
131        $a = Foo->new( 42 );
132        print "a=$$a\n";
133
134
135=head1 INSTANCE VARIABLE INHERITANCE
136
137This example demonstrates how one might inherit instance variables from a
138superclass for inclusion in the new class.  This requires calling the
139superclass's constructor and adding one's own instance variables to the new
140object.
141
142        package Bar;
143
144        sub new {
145                my $type = shift;
146                my $self = {};
147                $self->{'buz'} = 42;
148                bless $self, $type;
149        }
150
151        package Foo;
152        @ISA = qw( Bar );
153
154        sub new {
155                my $type = shift;
156                my $self = Bar->new;
157                $self->{'biz'} = 11;
158                bless $self, $type;
159        }
160
161        package main;
162
163        $a = Foo->new;
164        print "buz = ", $a->{'buz'}, "\n";
165        print "biz = ", $a->{'biz'}, "\n";
166
167
168
169=head1 OBJECT RELATIONSHIPS
170
171The following demonstrates how one might implement "containing" and "using"
172relationships between objects.
173
174        package Bar;
175
176        sub new {
177                my $type = shift;
178                my $self = {};
179                $self->{'buz'} = 42;
180                bless $self, $type;
181        }
182
183        package Foo;
184
185        sub new {
186                my $type = shift;
187                my $self = {};
188                $self->{'Bar'} = Bar->new;
189                $self->{'biz'} = 11;
190                bless $self, $type;
191        }
192
193        package main;
194
195        $a = Foo->new;
196        print "buz = ", $a->{'Bar'}->{'buz'}, "\n";
197        print "biz = ", $a->{'biz'}, "\n";
198
199
200
201=head1 OVERRIDING SUPERCLASS METHODS
202
203The following example demonstrates how to override a superclass method and
204then call the overridden method.  The B<SUPER> pseudo-class allows the
205programmer to call an overridden superclass method without actually knowing
206where that method is defined.
207
208        package Buz;
209        sub goo { print "here's the goo\n" }
210
211        package Bar; @ISA = qw( Buz );
212        sub google { print "google here\n" }
213
214        package Baz;
215        sub mumble { print "mumbling\n" }
216
217        package Foo;
218        @ISA = qw( Bar Baz );
219
220        sub new {
221                my $type = shift;
222                bless [], $type;
223        }
224        sub grr { print "grumble\n" }
225        sub goo {
226                my $self = shift;
227                $self->SUPER::goo();
228        }
229        sub mumble {
230                my $self = shift;
231                $self->SUPER::mumble();
232        }
233        sub google {
234                my $self = shift;
235                $self->SUPER::google();
236        }
237
238        package main;
239
240        $foo = Foo->new;
241        $foo->mumble;
242        $foo->grr;
243        $foo->goo;
244        $foo->google;
245
246Note that C<SUPER> refers to the superclasses of the current package
247(C<Foo>), not to the superclasses of C<$self>.
248
249
250=head1 USING RELATIONSHIP WITH SDBM
251
252This example demonstrates an interface for the SDBM class.  This creates a
253"using" relationship between the SDBM class and the new class Mydbm.
254
255        package Mydbm;
256
257        require SDBM_File;
258        require Tie::Hash;
259        @ISA = qw( Tie::Hash );
260
261        sub TIEHASH {
262            my $type = shift;
263            my $ref  = SDBM_File->new(@_);
264            bless {'dbm' => $ref}, $type;
265        }
266        sub FETCH {
267            my $self = shift;
268            my $ref  = $self->{'dbm'};
269            $ref->FETCH(@_);
270        }
271        sub STORE {
272            my $self = shift;
273            if (defined $_[0]){
274                my $ref = $self->{'dbm'};
275                $ref->STORE(@_);
276            } else {
277                die "Cannot STORE an undefined key in Mydbm\n";
278            }
279        }
280
281        package main;
282        use Fcntl qw( O_RDWR O_CREAT );
283
284        tie %foo, "Mydbm", "Sdbm", O_RDWR|O_CREAT, 0640;
285        $foo{'bar'} = 123;
286        print "foo-bar = $foo{'bar'}\n";
287
288        tie %bar, "Mydbm", "Sdbm2", O_RDWR|O_CREAT, 0640;
289        $bar{'Cathy'} = 456;
290        print "bar-Cathy = $bar{'Cathy'}\n";
291
292=head1 THINKING OF CODE REUSE
293
294One strength of Object-Oriented languages is the ease with which old code
295can use new code.  The following examples will demonstrate first how one can
296hinder code reuse and then how one can promote code reuse.
297
298This first example illustrates a class which uses a fully-qualified method
299call to access the "private" method BAZ().  The second example will show
300that it is impossible to override the BAZ() method.
301
302        package FOO;
303
304        sub new {
305                my $type = shift;
306                bless {}, $type;
307        }
308        sub bar {
309                my $self = shift;
310                $self->FOO::private::BAZ;
311        }
312
313        package FOO::private;
314
315        sub BAZ {
316                print "in BAZ\n";
317        }
318
319        package main;
320
321        $a = FOO->new;
322        $a->bar;
323
324Now we try to override the BAZ() method.  We would like FOO::bar() to call
325GOOP::BAZ(), but this cannot happen because FOO::bar() explicitly calls
326FOO::private::BAZ().
327
328        package FOO;
329
330        sub new {
331                my $type = shift;
332                bless {}, $type;
333        }
334        sub bar {
335                my $self = shift;
336                $self->FOO::private::BAZ;
337        }
338
339        package FOO::private;
340
341        sub BAZ {
342                print "in BAZ\n";
343        }
344
345        package GOOP;
346        @ISA = qw( FOO );
347        sub new {
348                my $type = shift;
349                bless {}, $type;
350        }
351
352        sub BAZ {
353                print "in GOOP::BAZ\n";
354        }
355
356        package main;
357
358        $a = GOOP->new;
359        $a->bar;
360
361To create reusable code we must modify class FOO, flattening class
362FOO::private.  The next example shows a reusable class FOO which allows the
363method GOOP::BAZ() to be used in place of FOO::BAZ().
364
365        package FOO;
366
367        sub new {
368                my $type = shift;
369                bless {}, $type;
370        }
371        sub bar {
372                my $self = shift;
373                $self->BAZ;
374        }
375
376        sub BAZ {
377                print "in BAZ\n";
378        }
379
380        package GOOP;
381        @ISA = qw( FOO );
382
383        sub new {
384                my $type = shift;
385                bless {}, $type;
386        }
387        sub BAZ {
388                print "in GOOP::BAZ\n";
389        }
390
391        package main;
392
393        $a = GOOP->new;
394        $a->bar;
395
396=head1 CLASS CONTEXT AND THE OBJECT
397
398Use the object to solve package and class context problems.  Everything a
399method needs should be available via the object or should be passed as a
400parameter to the method.
401
402A class will sometimes have static or global data to be used by the
403methods.  A subclass may want to override that data and replace it with new
404data.  When this happens the superclass may not know how to find the new
405copy of the data.
406
407This problem can be solved by using the object to define the context of the
408method.  Let the method look in the object for a reference to the data.  The
409alternative is to force the method to go hunting for the data ("Is it in my
410class, or in a subclass?  Which subclass?"), and this can be inconvenient
411and will lead to hackery.  It is better just to let the object tell the
412method where that data is located.
413
414        package Bar;
415
416        %fizzle = ( 'Password' => 'XYZZY' );
417
418        sub new {
419                my $type = shift;
420                my $self = {};
421                $self->{'fizzle'} = \%fizzle;
422                bless $self, $type;
423        }
424
425        sub enter {
426                my $self = shift;
427
428                # Don't try to guess if we should use %Bar::fizzle
429                # or %Foo::fizzle.  The object already knows which
430                # we should use, so just ask it.
431                #
432                my $fizzle = $self->{'fizzle'};
433
434                print "The word is ", $fizzle->{'Password'}, "\n";
435        }
436
437        package Foo;
438        @ISA = qw( Bar );
439
440        %fizzle = ( 'Password' => 'Rumple' );
441
442        sub new {
443                my $type = shift;
444                my $self = Bar->new;
445                $self->{'fizzle'} = \%fizzle;
446                bless $self, $type;
447        }
448
449        package main;
450
451        $a = Bar->new;
452        $b = Foo->new;
453        $a->enter;
454        $b->enter;
455
456=head1 INHERITING A CONSTRUCTOR
457
458An inheritable constructor should use the second form of bless() which allows
459blessing directly into a specified class.  Notice in this example that the
460object will be a BAR not a FOO, even though the constructor is in class FOO.
461
462        package FOO;
463
464        sub new {
465                my $type = shift;
466                my $self = {};
467                bless $self, $type;
468        }
469
470        sub baz {
471                print "in FOO::baz()\n";
472        }
473
474        package BAR;
475        @ISA = qw(FOO);
476
477        sub baz {
478                print "in BAR::baz()\n";
479        }
480
481        package main;
482
483        $a = BAR->new;
484        $a->baz;
485
486=head1 DELEGATION
487
488Some classes, such as SDBM_File, cannot be effectively subclassed because
489they create foreign objects.  Such a class can be extended with some sort of
490aggregation technique such as the "using" relationship mentioned earlier or
491by delegation.
492
493The following example demonstrates delegation using an AUTOLOAD() function to
494perform message-forwarding.  This will allow the Mydbm object to behave
495exactly like an SDBM_File object.  The Mydbm class could now extend the
496behavior by adding custom FETCH() and STORE() methods, if this is desired.
497
498        package Mydbm;
499
500        require SDBM_File;
501        require Tie::Hash;
502        @ISA = qw(Tie::Hash);
503
504        sub TIEHASH {
505                my $type = shift;
506                my $ref = SDBM_File->new(@_);
507                bless {'delegate' => $ref};
508        }
509
510        sub AUTOLOAD {
511                my $self = shift;
512
513                # The Perl interpreter places the name of the
514                # message in a variable called $AUTOLOAD.
515
516                # DESTROY messages should never be propagated.
517                return if $AUTOLOAD =~ /::DESTROY$/;
518
519                # Remove the package name.
520                $AUTOLOAD =~ s/^Mydbm:://;
521
522                # Pass the message to the delegate.
523                $self->{'delegate'}->$AUTOLOAD(@_);
524        }
525
526        package main;
527        use Fcntl qw( O_RDWR O_CREAT );
528
529        tie %foo, "Mydbm", "adbm", O_RDWR|O_CREAT, 0640;
530        $foo{'bar'} = 123;
531        print "foo-bar = $foo{'bar'}\n";
532
533=head1 SEE ALSO
534
535L<perlboot>, L<perltoot>, L<perltooc>.
Note: See TracBrowser for help on using the repository browser.