您的位置:首页 > 编程语言 > C#

用一个简单示例来说明C#中的继承、封装和多态

2012-01-06 18:50 706 查看
下面先来叙述一下问题的描述:要求设计一个能描述所有图形公共属性和方法的的类(Shape),然后设计若干个不同的继承Shape的子类,比如三角形、圆形,矩形等等,基本功能要求:能提供面积和周长的计算和输出

接着我们就来用C#语言的封装和继承的特性分析一下这个类和子类的设计吧,首先就是父类的设计,想一想父类应该包含哪些属性,或者方法呢,对于每个图形我们知道他们都有自己的周长和面积,因此我们可以将其周长和面积放到父类Shape中即可,对于所有具体的某种图形都应该有计算和输出其周长和面积的方法,那计算和输出的方法应该放到子类中呢还是父类中去呢,我们可以从其变化的角度来分析,对于不同图形来说,它们周长和面积的计算公式是不一样的,因此我们可以这样设计,在父类中只是声明计算周长和面积的抽象方法,然后在其子类中去具体的实现即可,再来考虑输出周长和面积的方法应该放到哪儿呢,是子类还是父类呢?在此我是这样设计的,将输出周长和面积的方法在父类中设计成共有虚拟的(即用public
virtual修饰的),这样做的好处是,子类的如果不去重写父类的输出方法,则默认调用父类的输出周长和面积的函数,若是子类对输出周长和面积的格式有一定的变化或者改进的话,子类就完全可以重写(overide)周长和面积输出方法,以满足子类的需要,当重写之后子类就会调用其重写后的方法,即使是转换成父类对象也是调用子类的重写的方法(这就是多态性的体现),好了分析就到这里吧;下面看看具体的代码实现:

在父类Shape代码实现如下:

/// <summary>
/// 所有图形形状的基类
/// </summary>
public abstract class Shape
{
private double _perimeter;
private double _area;
private string _shapename;

/// <summary>
/// 周长
/// </summary>
protected double Perimeter
{
get { return _perimeter; }
set { _perimeter = value;}
}

/// <summary>
/// 面积
/// </summary>
protected double Area
{
get { return _area; }
set { _area = value;}
}

/// <summary>
/// 形状的名称
/// </summary>
protected string ShapeName
{
get { return _shapename; }
set { _shapename = value; }
}

/// <summary>
/// 默认构造函数
/// </summary>
protected Shape()
{
_perimeter=0;
_area=0;
_shapename="";
}

/// <summary>
/// 输出周长
/// </summary>
public virtual void PrintPerimeter()
{
Console.WriteLine(ShapeName + "的周长为:"+this.CalculatePerimeter());
}

/// <summary>
/// 输出面积
/// </summary>
public virtual void PrintArea()
{
Console.WriteLine(ShapeName + "的面积为:"+this.CalculateArea());
}

/// <summary>
/// 计算周长(因该方法为抽象方法,因此必须在子类中进行重写)
/// </summary>
/// <returns></returns>
public  abstract double CalculatePerimeter();

/// <summary>
/// 计算面积(因该方法为抽象方法,因此必须在子类中进行重写)
/// </summary>
/// <returns></returns>
public  abstract double CalculateArea();
}

注:Shape类设计成抽象的,是因为它应该是所有形状的基类;只能作为某种具体形状的父类,不能被实例化

下面简单设计了一下子类圆和三角形类的实现:

圆类代码实现如下:

/// <summary>
/// 圆形
/// </summary>
public class Circle : Shape
{
const double PI=3.1415;
private double _r = 0;

/// <summary>
/// 圆的半径
/// </summary>
public double R
{
get { return _r; }
set { _r = value; }
}

/// <summary>
/// 默认构造函数
/// </summary>
public Circle(): base()
{
this.ShapeName ="圆";
}

public Circle(double r):this()
{
this.R = r;
}

/// <summary>
/// 设置半径
/// </summary>
/// <param name="r"></param>
public void SetRadius(double r)
{
this.R = r;
}

/// <summary>
/// 计算周长
/// </summary>
/// <returns></returns>
public override double CalculatePerimeter()
{
Perimeter = 2 * PI * R;
return Perimeter;
}

/// <summary>
/// 计算面积
/// </summary>
/// <returns></returns>
public override double CalculateArea()
{
Area = PI * R * R;
return Area;
}

/// <summary>
/// 重写父类虚拟的PrintArea方法输出面积
/// </summary>
public override void PrintArea()
{
Console.WriteLine("执行Circle.PrintArea()方法输出面积");
base.PrintArea();
}

/// <summary>
/// 重写父类虚拟的PrintPerimeter方法 输出周长
/// </summary>
public override void PrintPerimeter()
{
Console.WriteLine("执行Circle.PrintPerimeter()方法输出周长");
base.PrintPerimeter();
}
}


三角形类代码实现如下:

/// <summary>
/// 三角形
/// </summary>
public class Triangle:Shape
{
//私有字段
private double _a;
private double _b;
private double _c;

#region 属性成员
public double A
{
get { return _a; }
}

public double B
{
get { return _b; }
}

public double C
{
get { return _c; }
}
#endregion

/// <summary>
/// 继承基类默认构造函数
/// </summary>
public Triangle():base()
{
this.ShapeName="三角形";
}
/// <summary>
/// 构造函数(需传入三角形的三个边长)
/// </summary>
/// <param name="a">第一个边</param>
/// <param name="b">第二个边</param>
/// <param name="c">第三个边</param>
public Triangle(double a, double b, double c):this()
{

if (this.CheckSide(a, b, c) == true)
{
this._a = a;
this._b = b;
this._c = c;
}
}

/// <summary>
/// 设置三个边的长度
/// </summary>
/// <param name="a">第一个边</param>
/// <param name="b">第二个边</param>
/// <param name="c">第三个边</param>
public void SetThreeSideLength(double a, double b, double c)
{
if (this.CheckSide(a, b, c) == true)
{
this._a = a;
this._b = b;
this._c = c;
}
}

/// <summary>
/// 检查边长
/// </summary>
/// <param name="a">第一个边</param>
/// <param name="b">第二个边</param>
/// <param name="c">第三个边</param>
/// <returns></returns>
public bool CheckSide(double a, double b, double c)
{
if (a > 0 && b > 0 && c > 0)
{
if ((((a + b) > c && (a + c) > b && (b + c) > a) &&
(Math.Abs(a - b) < c && Math.Abs(a - c) < b && Math.Abs(b - c) < a)))
{
return true;
}
else
{
throw new ArgumentException("您输入的三个边长不能构成有效的三角形,请检查其边长!");
}
}
else
{
throw new ArgumentException("三个边长必须大于0!");
}
}

/// <summary>
/// 计算周长
/// </summary>
public override double CalculatePerimeter()
{
this.Perimeter = A + B + C;
return Perimeter;
}

/// <summary>
/// 计算面积
/// </summary>
public override double CalculateArea()
{
//已知三个边面积计算公式:S△=√〔p(p-a)(p-b)(p-c)〕 〔p=1/2(a+b+c)〕(海伦—秦九韶公式)
double P= (A + B + C) / 2;
Area = Math.Sqrt(P * (P - A) * (P - B) * (P - C));
return Area;
}
}


测试调用代码:

//Shape triangle = new Triangle(3,4,5);
//triangle.PrintArea();
//triangle.PrintPerimeter();

//Shape circle = new Circle(10);
//circle.PrintArea();
//circle.PrintPerimeter();
//Console.ReadKey();
Shape[] shapes = new Shape[]
{
new Circle(10),
new Circle(8),
new Circle(100),
new Triangle(3,4,5),
new Triangle(10,10,10),
new Triangle(8,10,12)
};
foreach (Shape shape in shapes)
{
Console.WriteLine("***********************************");
shape.PrintArea();
shape.PrintPerimeter();
Console.WriteLine("***********************************");
Console.WriteLine();
}
Console.ReadKey();


本篇博客只是我学习的理解和认识,希望对于刚学C#语言的朋友们理解继承、封装和多态有一定的帮助作用吧 ,有不对之处还望指正!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: