Raku kurss / Pielikums 🆕 / Tipi un teksta mašīnas / Objekti un klases / Exercises / Figūras ar kopīgu lomu
Risinājums: Figūras ar kopīgu lomu
Šeit ir iespējams risinājums uzdevumam.
Kods
role Shape {
method area { ... }
}
class Circle does Shape {
has $.radius;
method area { 3.14159 * $.radius ** 2 }
}
class Square does Shape {
has $.side;
method area { $.side ** 2 }
}
sub describe(Shape $shape) {
say "{$shape.^name}: {$shape.area}";
}
for Circle.new(radius => 2), Square.new(side => 3) -> $shape {
describe($shape);
}🦋 Atrodiet programmu failā shapes-role.raku.
Izvade
Circle: 12.56636
Square: 9Komentāri
Stingri ņemot, izsaukums
$shape.areastrādātu arī bez lomas. Raku metodes atrisina pēc nosaukuma izsaukuma brīdī, tāpēc, kamēr vien katram objektam gadās būt metodeiarea, cikls darbojas — to sauc par pīļu tipizēšanu. Ko tad loma mums šeit patiesībā dod? Divas garantijas.Loma ir tips, ko var pieprasīt.
describeir deklarēta kāsub describe(Shape $shape), tāpēc tā pieņem tikai objektus, kas pildaShape, un atsaka visu citu pirms ķermeņa izpildes. Padodiet tai parastu skaitli, un programma atsakās kompilēties:describe(42); # Calling describe(Int) will never work with declared signature (Shape $shape)
Bez lomas tāda tipa nav — pīļu tipizēta procedūra pieņemtu jebkuru argumentu un uzsprāgtu tikai vēlāk, dziļi iekšā, kad tā nonāktu līdz
.area.Loma ir līgums. Deklarējot
areakā aizvietni (method area { ... }), katrai klasei, kas pilda lomu, tiek uzlikts par pienākumu piegādāt savuarea. Aizmirstiet to, un kļūda nevar palikt nepamanīta:class Triangle does Shape { has $.base; has $.height; } # Method 'area' must be implemented by Triangle because it is required by roles: Shape. my $t = Triangle.new(base => 3, height => 4); say $t.area; # Stub code executed
Rakudo par trūkstošo metodi paziņo, tiklīdz klase tiek komponēta, — programma atsakās kompilēties, pirms vēl pastāv kaut viens
Triangleobjekts. Un pat realizācijā, kas klases definīciju pieņemtu, kļūda atklājas vēlākais tad, kad metodi lieto: no lomas mantotā aizvietne{ ... }ir īsts kods, kas nomirst arStub code executed, tiklīdz kāds to izsauc.$shape.^nameobjektam pajautā tā klases nosaukumu, tāpēc viena un tā patidescribekatru rezultātu apzīmē pareizi, iepriekš nezinot tipu.