Depois que você tiver uma boa idéia sobre os métodos comuns a cada tipo de forma, você pode definir as próprias classes. Em termos da quantidade dos métodos precisam ser implementados, a forma mais simples é a da classe Circle, mostrada aqui:
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;
}
}
}
A classe Circle implementa a interface IGeometricShape, portanto ela deve fornecer código para os métodos
getArea()
e
describe()
. Além disso, ela define o método
getCircumference()
que é exclusivo à classe Circle. A classe Circle também declara uma propriedade,
diameter
que não é encontrada nas outras classes de polígonos.
Os dois outros tipos de formas, quadrados e triângulos eqüiláteros, têm algumas outras coisas em comum: cada um deles têm lados com o mesmo comprimento e há fórmulas comuns que você pode usar para calcular o perímetro e a soma dos ângulos internos dos dois. Na verdade, essas fórmulas comuns são aplicadas a todos os outros polígonos regulares que você definir no futuro.
A classe RegularPolygon é a superclasse das classes Square e EquilateralTriangle. Uma superclasse permite definir métodos comuns em um lugar, portanto você não precisa defini-los separadamente em cada subclasse. Este é o código da classe 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;
}
}
}
Primeiro, a classe RegularPolygon declara duas propriedades comuns a todos os polígonos regulares: o comprimento de cada lado (a propriedade
sideLength
) e o número de lados (a propriedade
numSides
).
A classe RegularPolygon implementa a interface IPolygon e declara os quatro métodos da interface IPolygon. Ela implementa dois desses, os métodos
getPerimeter()
e
getSumOfAngles()
, usando fórmulas comuns.
Como a fórmula do método
getArea()
é diferente de forma para forma, a versão da classe base do método não pode incluir a lógica comum que pode ser herdada pelos métodos da subclasse. Em vez disso, ele simplesmente retorna um valor padrão 0 para indicar que a área não foi calculada. Para calcular a área de cada forma corretamente, as próprias subclasses da classe RegularPolygon precisam substituir o método
getArea()
.
O seguinte código da classe EquilateralTriangle mostra como o método
getArea()
é substituído:
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;
}
}
}
A palavra-chave
override
indica que o método
EquilateralTriangle.getArea()
substitui intencionalmente o método
getArea()
da superclasse RegularPolygon. Quando o método
EquilateralTriangle.getArea()
é chamado, ele calcula a área usando a fórmula do código anterior, e o código no método
RegularPolygon.getArea()
nunca é executado.
Em comparação, a classe EquilateralTriangle não define sua própria versão do método
getPerimeter()
. Quando o método
EquilateralTriangle.getPerimeter()
é chamado, a chamada percorre a cadeia de herança e executa o código no método
getPerimeter()
da superclasse RegularPolygon.
O construtor
EquilateralTriangle()
usa a instrução
super()
para chamar explicitamente o construtor
RegularPolygon()
de sua superclasse. Se os dois construtores tivessem o mesmo conjunto de parâmetros, você poderia omitir completamente o construtor
EquilateralTriangle()
e o construtor
RegularPolygon()
seria executado. No entanto, o construtor
RegularPolygon()
precisa de um parâmetro extra,
numSides
. Portanto, o construtor
EquilateralTriangle()
chama
super(len, 3)
que passa o parâmetro de entrada
len
e o valor 3 para indicar que o triângulo tem três lados.
O método
describe()
também usa a instrução
super()
, mas de forma diferente. Ele a utiliza para invocar a versão da superclasse RegularPolygon do método
describe()
. O método
EquilateralTriangle.describe()
define primeiro a variável da string
desc
como uma instrução sobre o tipo da forma. Em seguida, ele obtém os resultados do método
RegularPolygon.describe()
chamando
super.describe()
e anexa esse resultado à string
desc
.
A classe Square não é descrita em detalhes aqui, mas é semelhante à classe EquilateralTriangle, fornecendo um construtor e suas próprias implementações dos métodos
getArea()
e
describe()
.