@@ -145,7 +145,8 @@ key principles of object oriented design.
145
145
The first declaration specifies instance storage for a callback – a bit of
146
146
code to invoke in order to perform the task that an object represents:
147
147
148
- has &!callback;
148
+ = for code :skip-test
149
+ has &!callback;
149
150
150
151
X < |sigils,& >
151
152
X < |twigils >
@@ -158,7 +159,8 @@ this attribute is private to the class.
158
159
159
160
The second declaration also uses the private twigil:
160
161
161
- has Task @!dependencies;
162
+ = for code :skip-test
163
+ has Task @!dependencies;
162
164
163
165
However, this attribute represents an array of items, so it requires the
164
166
C < @ > sigil. These items each specify a task that must be completed before
@@ -168,7 +170,8 @@ class (or some subclass of it).
168
170
169
171
The third attribute represents the state of completion of a task:
170
172
171
- has Bool $.done;
173
+ = for code :skip-test
174
+ has Bool $.done;
172
175
173
176
X < |twigils,. >
174
177
X < |twigils,accessors >
@@ -210,26 +213,27 @@ those with and without accessors):
210
213
The assignment is carried out at object build time. The right-hand side is
211
214
evaluated at that time, and can even reference earlier attributes:
212
215
213
- has Task @!dependencies;
214
- has $.ready = not @!dependencies;
216
+ = for code :skip-test
217
+ has Task @!dependencies;
218
+ has $.ready = not @!dependencies;
215
219
216
220
= head1 Static fields?
217
221
218
222
Perl 6 has no B < static > keyword. Nevertheless, any class may declare anything
219
223
that a module can, so making a scoped variable sounds like good idea.
220
224
221
- = begin code
225
+ = begin code
222
226
223
- class Singleton {
224
- my Singleton $instance;
225
- method new {!!!}
226
- submethod instance {
227
- $instance = Singleton.bless unless $instance;
228
- $instance;
229
- }
230
- }
227
+ class Singleton {
228
+ my Singleton $instance;
229
+ method new {!!!}
230
+ submethod instance {
231
+ $instance = Singleton.bless unless $instance;
232
+ $instance;
233
+ }
234
+ }
231
235
232
- = end code
236
+ = end code
233
237
234
238
Class attributes defined by L < my|/syntax/my > or L < our|/syntax/our > may also be initialized when
235
239
being declared, however we are implementing the Singleton pattern here and
@@ -238,9 +242,11 @@ predict the moment when attribute initialization will be executed, because
238
242
it can take place during compilation, runtime or both, especially when
239
243
importing the class using the L < use|/syntax/use > keyword.
240
244
245
+ = begin code :skip-test
241
246
class HaveStaticAttr {
242
247
my Foo $.foo = some_complicated_subroutine;
243
248
}
249
+ = end code
244
250
245
251
Class attributes may also be declared with a secondary sigil – in a similar
246
252
manner to object attributes – that will generate read-only accessors if the
@@ -256,9 +262,11 @@ ignore the C<new> method temporarily; it's a special type of method.
256
262
Consider the second method, C < add-dependency > , which adds a new task to a
257
263
task's dependency list.
258
264
265
+ = begin code :skip-test
259
266
method add-dependency(Task $dependency) {
260
267
push @!dependencies, $dependency;
261
268
}
269
+ = end code
262
270
263
271
X < |invocant >
264
272
@@ -274,13 +282,15 @@ attribute.
274
282
275
283
The C < perform > method contains the main logic of the dependency handler:
276
284
285
+ = begin code :skip-test
277
286
method perform() {
278
287
unless $!done {
279
288
.perform() for @!dependencies;
280
289
&!callback();
281
290
$!done = True;
282
291
}
283
292
}
293
+ = end code
284
294
285
295
It takes no parameters, working instead with the object's attributes. First,
286
296
it checks if the task has already completed by checking the C < $!done >
@@ -377,7 +387,8 @@ allowed to bind things to C<&!callback> and C<@!dependencies> directly. To
377
387
do this, we override the C < BUILD > submethod, which is called on the brand
378
388
new object by C < bless > :
379
389
380
- submethod BUILD(:&!callback, :@!dependencies) { }
390
+ = for code :skip-test
391
+ submethod BUILD(:&!callback, :@!dependencies) { }
381
392
382
393
Since C < BUILD > runs in the context of the newly created C < Task > object, it
383
394
is allowed to manipulate those private attributes. The trick here is that
@@ -389,6 +400,7 @@ more information.
389
400
The C < BUILD > method is responsible for initializing all attributes and must also
390
401
handle default values:
391
402
403
+ = begin code :skip-test
392
404
has &!callback;
393
405
has @!dependencies;
394
406
has Bool ($.done, $.ready);
@@ -398,6 +410,7 @@ handle default values:
398
410
:$!done = False,
399
411
:$!ready = not @!dependencies
400
412
) { }
413
+ = end code
401
414
402
415
See L < Object Construction|/language/objects#Object_Construction > for more
403
416
options to influence object construction and attribute initialization.
@@ -408,7 +421,8 @@ After creating a class, you can create instances of the class. Declaring a
408
421
custom constructor provides a simple way of declaring tasks along with their
409
422
dependencies. To create a single task with no dependencies, write:
410
423
411
- my $eat = Task.new({ say 'eating dinner. NOM!' });
424
+ = for code :skip-test
425
+ my $eat = Task.new({ say 'eating dinner. NOM!' });
412
426
413
427
An earlier section explained that declaring the class C < Task > installed a
414
428
type object in the namespace. This type object is a kind of "empty
@@ -419,6 +433,7 @@ modifying or accessing an existing object.
419
433
420
434
Unfortunately, dinner never magically happens. It has dependent tasks:
421
435
436
+ = begin code :skip-test
422
437
my $eat =
423
438
Task.new({ say 'eating dinner. NOM!' },
424
439
Task.new({ say 'making dinner' },
@@ -429,18 +444,21 @@ Unfortunately, dinner never magically happens. It has dependent tasks:
429
444
Task.new({ say 'cleaning kitchen' })
430
445
)
431
446
);
447
+ = end code
432
448
433
449
Notice how the custom constructor and sensible use of whitespace makes task dependencies clear.
434
450
435
451
Finally, the C < perform > method call recursively calls the C < perform > method
436
452
on the various other dependencies in order, giving the output:
437
453
454
+ = begin code :skip-test
438
455
making some money
439
456
going to the store
440
457
buying food
441
458
cleaning kitchen
442
459
making dinner
443
460
eating dinner. NOM!
461
+ = end code
444
462
445
463
= head1 Inheritance
446
464
@@ -477,7 +495,7 @@ other means, such as attribute accessors.
477
495
Now, any object of type Programmer can make use of the methods and accessors
478
496
defined in the Employee class as though they were from the Programmer class.
479
497
480
- = begin code
498
+ = begin code :skip-test
481
499
my $programmer = Programmer.new(
482
500
salary => 100_000,
483
501
known_languages => <Perl5 Perl6 Erlang C++>,
@@ -494,7 +512,7 @@ Of course, classes can override methods and attributes defined by parent
494
512
classes by defining their own. The example below demonstrates the C < Baker >
495
513
class overriding the C < Cook > 's C < cook > method.
496
514
497
- = begin code
515
+ = begin code :skip-test
498
516
class Cook is Employee {
499
517
has @.utensils is rw;
500
518
has @.cookbooks is rw;
@@ -545,7 +563,7 @@ algorithm to linearize multiple inheritance hierarchies, which is a
545
563
significant improvement over Perl 5's default approach
546
564
(depth-first search) to handling multiple inheritance.
547
565
548
- = begin code
566
+ = begin code :skip-test
549
567
class GeekCook is Programmer is Cook {
550
568
method new( *%params ) {
551
569
push( %params<cookbooks>, "Cooking for Geeks" );
@@ -580,6 +598,7 @@ Classes to be inherited from can be listed in the class declaration body by
580
598
prefixing the C < is > trait with C < also > . This also works for the role
581
599
composition trait C < does > .
582
600
601
+ = begin code :skip-test
583
602
class GeekCook {
584
603
also is Programmer;
585
604
also is Cook;
@@ -589,6 +608,7 @@ composition trait C<does>.
589
608
role A {};
590
609
role B {};
591
610
class C { also does A; also does B }
611
+ = end code
592
612
593
613
= head1 Introspection
594
614
@@ -599,21 +619,25 @@ a controlling object) for some properties, such as its type.
599
619
Given an object C < $o > and the class definitions from the previous sections,
600
620
we can ask it a few questions:
601
621
622
+ = begin code :skip-test
602
623
if $o ~~ Employee { say "It's an employee" };
603
624
if $o ~~ GeekCook { say "It's a geeky cook" };
604
625
say $o.WHAT;
605
626
say $o.perl;
606
627
say $o.^methods(:local)».name.join(', ');
607
628
say $o.^name;
629
+ = end code
608
630
609
631
The output can look like this:
610
632
633
+ = begin code :skip-test
611
634
It's an employee
612
635
(Programmer)
613
636
Programmer.new(known_languages => ["Perl", "Python", "Pascal"],
614
637
favorite_editor => "gvim", salary => "too small")
615
638
code_to_solve, known_languages, favorite_editor
616
639
Programmer
640
+ = end code
617
641
618
642
The first two tests each smart-match against a class name. If the object is
619
643
of that class, or of an inheriting class, it returns true. So the object in
@@ -640,8 +664,9 @@ it is actually a method call on its I<meta class>, which is a class managing
640
664
the properties of the C < Programmer > class – or any other class you are
641
665
interested in. This meta class enables other ways of introspection too:
642
666
643
- say $o.^attributes.join(', ');
644
- say $o.^parents.map({ $_.^name }).join(', ');
667
+ = for code :skip-test
668
+ say $o.^attributes.join(', ');
669
+ say $o.^parents.map({ $_.^name }).join(', ');
645
670
646
671
Finally C < $o.^name > calls the C < name > method on the meta object, which
647
672
unsurprisingly returns the class name.
0 commit comments