Curso de Raku / Apéndice 🆕 / Tipos y máquinas de texto / Objetos y clases / Exercises / Figuras que comparten un rol
Solución: Figuras que comparten un rol
Aquí tienes una posible solución para la tarea.
Código
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);
}🦋 Puedes encontrar el código fuente en el archivo shapes-role.raku.
Salida
Circle: 12.56636
Square: 9Comentarios
En rigor, la llamada
$shape.areafuncionaría sin el rol en absoluto. Raku resuelve los métodos por nombre en el momento de la llamada, así que mientras cada objeto tenga por casualidad un métodoarea, el bucle funciona; esto se conoce como tipado pato. Entonces, ¿qué nos aporta aquí el rol en realidad? Dos garantías.El rol es un tipo que puedes exigir.
describese declara comosub describe(Shape $shape), así que acepta solo objetos que haganShapey rechaza cualquier otra cosa antes de que se ejecute el cuerpo. Pásale un número corriente y el programa se niega a compilar:describe(42); # Calling describe(Int) will never work with declared signature (Shape $shape)
Sin el rol no existe ese tipo: una rutina con tipado pato aceptaría cualquier argumento y solo reventaría más tarde, muy adentro, al llegar a
.area.El rol es un contrato. Declarar
areacomo un esbozo (method area { ... }) obliga a toda clase que haga el rol a proporcionar su propioarea. Olvídalo y el error no puede pasar inadvertido: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 informa del método ausente en cuanto la clase se compone: el programa se niega a compilar antes de que exista un solo objeto
Triangle. E incluso en una implementación que aceptara la definición de la clase, el error sale a la luz a más tardar cuando se usa el método: el esbozo{ ... }heredado del rol es código real que muere conStub code executeden cuanto alguien lo llama.$shape.^namele pregunta al objeto el nombre de su clase, así que el mismodescribeetiqueta cada resultado correctamente sin conocer el tipo de antemano.