Dès que vous avez une vue claire des méthodes communes à chaque type de forme, vous pouvez définir les classes de formes elles-mêmes. En ce qui concerne le nombre de méthodes à implémenter, la forme la plus simple est la classe Circle :
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 classe Circle implémente l’interface IGeometricShape. Elle doit donc comporter du code pour les méthodes
getArea()
et
describe()
. De plus, elle définit la méthode
getCircumference()
qui est unique à la classe Circle. La classe Circle déclare aussi une propriété,
diameter
, qui n’apparaîtra pas dans les autres classes, dédiées aux polygones.
Les deux autres types de formes, les carrés et les triangles équilatéraux, ont d’autres points communs : ils ont tous deux des côtés de longueur égale et il existe des formules communes pour calculer leurs périmètre et la somme de leurs angles intérieurs. En fait, ces formules communes s’appliquent à tout autre polygone régulier que vous définissez par la suite.
La classe RegularPolygon est la superclasse de la classe Square et de la classe EquilateralTriangle. Une superclasse permet de définir en un seul point des méthodes communes. Il n’est donc pas nécessaire de les définir séparément dans chaque sous-classe. Voici le code de la 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;
}
}
}
La classe RegularPolygon déclare d’abord deux propriétés qui sont communes à tous les polygones réguliers : la longueur de chaque côté (la propriété
sideLength
) et le nombre de faces (la propriété
numSides
).
La classe RegularPolygon implémente l’interface IPolygon et déclare les quatre méthodes de l’interface IPolygon. Elle implémente deux d’entre elles, les méthodes
getPerimeter()
et
getSumOfAngles()
à l’aide de formules communes.
La formule de la méthode
getArea()
étant différente d’une forme à l’autre, la version de la méthode dans la classe de base ne peut pas comporter une logique commune dont hériteraient les méthodes des sous-classes. Elle renvoie donc simplement une valeur 0 par défaut pour indiquer que la surface n’a pas été calculée. Pour calculer correctement la surface de chaque forme, les sous-classes de la classe RegularPolygon doivent redéfinir elles-mêmes la méthode
getArea()
.
Le code de la classe EquilateralTriangle, ci-dessous, montre comment la méthode
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;
}
}
}
Le mot-clé
override
indique que la méthode
EquilateralTriangle.getArea()
redéfinit volontairement la méthode
getArea()
de la superclasse RegularPolygon. Lorsque la méthode
EquilateralTriangle.getArea()
est appelée, elle calcule la surface à l’aide de la formule du code précédent. Le code de la méthode
RegularPolygon.getArea()
n’est jamais exécuté.
Par contre, la classe EquilateralTriangle ne définit pas sa propre version de la méthode
getPerimeter()
. Lorsque la méthode
EquilateralTriangle.getPerimeter()
est appelée, l’appel remonte la chaîne d’héritage et exécute le code de la méthode
getPerimeter()
de la superclasse RegularPolygon.
Le constructeur
EquilateralTriangle()
utilise l’instruction
super()
pour invoquer explicitement le constructeur
RegularPolygon()
de sa superclasse. Si les deux constructeurs avaient le même ensemble de paramètres, il serait possible d’omettre complètement le constructeur
EquilateralTriangle
et il suffirait d’exécuter le constructeur
RegularPolygon()
. Toutefois, le constructeur
RegularPolygon()
nécessite un paramètre supplémentaire,
numSides
. Le constructeur
EquilateralTriangle()
appelle donc
super(len, 3)
qui transmet le paramètre en entrée
len
et la valeur 3 pour indiquer que le triangle possède trois côtés.
La méthode
describe()
utilise également l’instruction
super()
, mais de façon différente, afin d’appeler la version de la méthode
describe()
figurant dans la superclasse RegularPolygon. La méthode
EquilateralTriangle.describe()
définit d’abord la variable de chaîne
desc
qui affiche le type de forme. Elle obtient ensuite les résultats de la méthode
RegularPolygon.describe()
en appelant
super.describe()
et elle ajoute ces résultats à la fin de la chaîne
desc
.
La classe Square n’est pas décrite en détail ici, mais elle est similaire à la classe EquilateralTriangle, avec un constructeur et ses propres implémentations des méthodes
getArea()
et
describe()
.