Cuando ya se conozcan los métodos comunes a cada tipo de forma, se pueden definir las clases de las formas. Por la cantidad de métodos que hay que implementar, la forma más sencilla es la clase Circle, que se muestra a continuación:
package com.example.programmingas3.geometricshapes
{
public class Circle implements IGeometricShape
{
public var diameter:Number;
public function Circle(diam:Number = 100):void
{
this.diameter = diam;
}
public function getArea():Number
{
// The formula is Pi * radius * radius.
var radius:Number = diameter / 2;
return Math.PI * radius * radius;
}
public function getCircumference():Number
{
// The formula is Pi * diameter.
return Math.PI * diameter;
}
public function describe():String
{
var desc:String = "This shape is a Circle.\n";
desc += "Its diameter is " + diameter + " pixels.\n";
desc += "Its area is " + getArea() + ".\n";
desc += "Its circumference is " + getCircumference() + ".\n";
return desc;
}
}
}
La clase Circle implementa la interfaz IGeometricShape, por lo que hay que proporcionar código para el método
getArea()
y el método
describe()
. Además, define el método
getCircumference()
, que es único para la clase Circle. La clase Circle también declara una propiedad,
diameter
, que no se encuentra en las clases de los otros polígonos.
Los otros dos tipos de formas, cuadrados y triángulos equiláteros, tienen algunos aspectos en común: cada uno de ellos tiene lados de longitud simular y existen fórmulas comunes que se pueden utilizar para calcular el perímetro y la suma de los ángulos interiores para ambos. De hecho, esas fórmulas comunes se aplicarán a cualquier otro polígono regular que haya que definir en el futuro.
La clase RegularPolygon será la superclase para la clase Square y la clase EquilateralTriangle. Una superclase permite centralizar la definición de métodos comunes de forma que no sea necesario definirlos por separado en cada subclase. A continuación se muestra el código para la clase RegularPolygon:
package com.example.programmingas3.geometricshapes
{
public class RegularPolygon implements IPolygon
{
public var numSides:int;
public var sideLength:Number;
public function RegularPolygon(len:Number = 100, sides:int = 3):void
{
this.sideLength = len;
this.numSides = sides;
}
public function getArea():Number
{
// This method should be overridden in subclasses.
return 0;
}
public function getPerimeter():Number
{
return sideLength * numSides;
}
public function getSumOfAngles():Number
{
if (numSides >= 3)
{
return ((numSides - 2) * 180);
}
else
{
return 0;
}
}
public function describe():String
{
var desc:String = "Each side is " + sideLength + " pixels long.\n";
desc += "Its area is " + getArea() + " pixels square.\n";
desc += "Its perimeter is " + getPerimeter() + " pixels long.\n";
desc += "The sum of all interior angles in this shape is " + getSumOfAngles() + " degrees.\n";
return desc;
}
}
}
En primer lugar, la clase RegularPolygon declara dos propiedades que son comunes a todos los polígonos regulares: la longitud de cada lado (propiedad
sideLength
) y el número de lados (propiedad
numSides
).
La clase RegularPolygon implementa la interfaz IPolygon y declara los cuatro métodos de la interfaz IPolygon. Implementa dos de ellos,
getPerimeter()
y
getSumOfAngles()
, utilizando fórmulas comunes.
Como la fórmula para el método
getArea()
varía de una forma a otra, la versión de la clase base del método no puede incluir lógica común que pueda ser heredada por los métodos de la subclase. Sólo devuelve el valor predeterminado 0, para indicar que no se ha calculado el área. Para calcular el área de cada forma correctamente, las subclases de la clase RegularPolygon tendrán que sustituir el método
getArea()
.
El código siguiente para la clase EquilateralTriangle muestra cómo se sustituye el método
getArea()
:
package com.example.programmingas3.geometricshapes
{
public class EquilateralTriangle extends RegularPolygon
{
public function EquilateralTriangle(len:Number = 100):void
{
super(len, 3);
}
public override function getArea():Number
{
// The formula is ((sideLength squared) * (square root of 3)) / 4.
return ( (this.sideLength * this.sideLength) * Math.sqrt(3) ) / 4;
}
public override function describe():String
{
/* starts with the name of the shape, then delegates the rest
of the description work to the RegularPolygon superclass */
var desc:String = "This shape is an equilateral Triangle.\n";
desc += super.describe();
return desc;
}
}
}
La palabra clave
override
indica que el método
EquilateralTriangle.getArea()
sustituye de forma intencionada el método
getArea()
de la superclase RegularPolygon. Cuando se llama al método
EquilateralTriangle.getArea()
, se calcula el área con la fórmula del fragmento de código anterior y no se ejecuta el código del método
RegularPolygon.getArea()
.
En cambio, la clase EquilateralTriangle no define su propia versión del método
getPerimeter()
. Cuando se llama al método
EquilateralTriangle.getPerimeter()
, la llamada sube por la cadena de herencia y ejecuta el código del método
getPerimeter()
de la superclase RegularPolygon.
El constructor de
EquilateralTriangle()
utiliza la sentencia
super()
para invocar explícitamente el constructor de
RegularPolygon()
de su superclase. Si ambos constructores tuvieran el mismo conjunto de parámetros, se podría omitir el constructor de
EquilateralTriangle()
y se ejecutaría en su lugar el constructor de
RegularPolygon()
. No obstante, el constructor de
RegularPolygon()
requiere un parámetro adicional,
numSides
. Así, el constructor de
EquilateralTriangle()
llama a
super(len, )
, que pasa el parámetro de entrada
len
y el valor 3 para indicar que el triángulo tendrá tres lados.
El método
describe()
también utiliza la sentencia
super()
, pero de un modo diferente. La utiliza para invocar a la versión de la superclase RegularPolygon del método
describe()
. El método
EquilateralTriangle.describe()
establece primero la variable de cadena
desc
en una declaración del tipo de forma. A continuación, obtiene los resultados del método
RegularPolygon.describe()
llamando a
super.describe()
y añade el resultado a la cadena
desc
.
No se proporciona en esta sección una descripción detallada de la clase Square, pero es similar a la clase EquilateralTriangle; proporciona un constructor y su propia implementación de los métodos
getArea()
y
describe()
.