对每种形状的方法有所了解后,就可以定义形状类本身了。就需要实现的方法数而言,最简单的形状是 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;
}
}
}
Circle 类用于实现 IGeometricShape 接口,因此,它必须为
getArea()
方法和
describe()
方法提供代码。此外,它还定义
getCircumference()
方法,该方法对 Circle 类是唯一的。另外,Circle 类还声明属性
diameter
,其他多边形类没有该属性。
其他两种形状,即正方形和等边三角形的某些其他方面是共同的:它们各自的边长相等,各自都有可用于计算周长和内角总和的通用公式。实际上,这些通用公式还适用于将来定义的任何其他正多边形。
RegularPolygon 类是 Square 和 EquilateralTriangle 两个类的超类。使用超类可在一个位置定义通用方法,所以不必在每个子类中单独定义方法。以下是 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;
}
}
}
第一,RegularPolygon 类用于声明所有正多边形的两个通用属性:每边的长度(
sideLength
属性)和边数(
numSides
属性)。
RegularPolygon 类实现 IPolygon 接口,还声明 IPolygon 接口的所有四个方法。它使用通用公式来实现
getPerimeter()
和
getSumOfAngles()
两种方法。
因为用于
getArea()
方法的公式因形状的不同而有所不同,所以该方法的基类版本不能包括可由子类方法继承的通用逻辑,而是只返回默认值 0 以指明未计算面积。要正确计算每个形状的面积,RegularPolygon 类的子类本身必须覆盖
getArea()
方法本身。
EquilateralTriangle 类的以下代码说明如何覆盖
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;
}
}
}
override
关键字指示
EquilateralTriangle.getArea()
方法有意覆盖 RegularPolygon 超类中的
getArea()
方法。当调用
EquilateralTriangle.getArea()
方法时,该方法使用先前代码中的公式计算面积,从不执行
RegularPolygon.getArea()
方法中的代码。
不同的是,EquilateralTriangle 类并不定义它自己版本的
getPerimeter()
方法。当调用
EquilateralTriangle.getPerimeter()
方法时,调用会沿继承链找到 RegularPolygon 超类的
getPerimeter()
方法,并执行其中的代码。
EquilateralTriangle()
构造函数使用
super()
语句显式地调用其超类的
RegularPolygon()
构造函数。如果这两个构造函数使用同一组参数,则可以完全省略
EquilateralTriangle()
构造函数,而执行
RegularPolygon()
构造函数。但是,
RegularPolygon()
构造函数需要额外的参数,即
numSides
。因此
EquilateralTriangle()
构造函数调用
super(len,3)
,该语句传递
len
输入参数和值 3,以表示三角形有三个边。
describe()
方法还使用
super()
语句,但使用方式不同。它使用该语句调用
describe()
方法的 RegularPolygon 超类版本。
EquilateralTriangle.describe()
方法先将
desc
字符串变量设置为有关形状类型的语句。然后调用
super.describe()
来获取
RegularPolygon.describe()
方法的结果,之后将结果追加到
desc
字符串。
此处不详细讨论 Square 类,但它类似于 EquilateralTriangle 类,提供构造函数及构造函数自己的
getArea()
和
describe()
方法的实现。