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