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