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

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

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

在父类Shape代码实现如下:

 1      /// <summary>
 2      /// 所有图形形状的基类
 3     /// </summary>
 4     public abstract class Shape
 5     {
 6         private double _perimeter;
 7         private double _area;
 8         private string _shapename;
 9 
10         /// <summary>
11         /// 周长
12         /// </summary>
13         protected double Perimeter
14         {
15             get { return _perimeter; }
16             set { _perimeter = value;}
17         }
18 
19         /// <summary>
20         /// 面积
21         /// </summary>
22         protected double Area
23         {
24             get { return _area; }
25             set { _area = value;}
26         }
27 
28         /// <summary>
29         /// 形状的名称
30         /// </summary>
31         protected string ShapeName
32         {
33             get { return _shapename; }
34             set { _shapename = value; }
35         }
36 
37         /// <summary>
38         /// 默认构造函数
39         /// </summary>
40         protected Shape()
41         { 
42       _perimeter=0;
43            _area=0;
44           _shapename="";       
45         }
46 
47         /// <summary>
48         /// 输出周长
49         /// </summary>
50         public virtual void PrintPerimeter()
51         {
52             Console.WriteLine(ShapeName + "的周长为:"+this.CalculatePerimeter());
53         }
54 
55         /// <summary>
56         /// 输出面积
57         /// </summary>
58         public virtual void PrintArea()
59         {
60             Console.WriteLine(ShapeName + "的面积为:"+this.CalculateArea());
61         }
62 
63         /// <summary>
64         /// 计算周长(因该方法为抽象方法,因此必须在子类中进行重写)
65         /// </summary>
66         /// <returns></returns>
67         public  abstract double CalculatePerimeter();
68 
69         /// <summary>
70         /// 计算面积(因该方法为抽象方法,因此必须在子类中进行重写)
71         /// </summary>
72         /// <returns></returns>
73         public  abstract double CalculateArea();
74     }
查看代码

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

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

圆类代码实现如下:

 1   /// <summary>
 2      /// 圆形
 3     /// </summary>
 4     public class Circle : Shape
 5     {
 6         const double PI=3.1415;
 7         private double _r = 0;
 8 
 9         /// <summary>
10         /// 圆的半径
11         /// </summary>
12         public double R
13         {
14             get { return _r; }
15             set { _r = value; }
16         }
17 
18         /// <summary>
19         /// 默认构造函数
20         /// </summary>
21         public Circle(): base()
22         {
23             this.ShapeName ="";
24         }
25 
26         public Circle(double r):this()
27         {
28              this.R = r;
29         }
30 
31         /// <summary>
32         /// 设置半径
33         /// </summary>
34         /// <param name="r"></param>
35         public void SetRadius(double r)
36         {
37             this.R = r;
38         }
39 
40         /// <summary>
41         /// 计算周长
42         /// </summary>
43         /// <returns></returns>
44         public override double CalculatePerimeter()
45         {
46             Perimeter = 2 * PI * R;
47             return Perimeter;
48         }
49 
50         /// <summary>
51         /// 计算面积
52         /// </summary>
53         /// <returns></returns>
54         public override double CalculateArea()
55         {
56             Area = PI * R * R;
57             return Area;
58         }
59 
60         /// <summary>
61         /// 重写父类虚拟的PrintArea方法输出面积
62         /// </summary>
63         public override void PrintArea()
64         {
65             Console.WriteLine("执行Circle.PrintArea()方法输出面积");
66             base.PrintArea();
67         }
68 
69         /// <summary>
70         /// 重写父类虚拟的PrintPerimeter方法 输出周长
71         /// </summary>
72         public override void PrintPerimeter()
73         {
74             Console.WriteLine("执行Circle.PrintPerimeter()方法输出周长");
75             base.PrintPerimeter();
76         }
77     }
查看代码

 三角形类代码实现如下:

   /// <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;
        }
    }
查看代码

测试调用代码:

 1               //Shape triangle = new Triangle(3,4,5);
 2              //triangle.PrintArea();
 3             //triangle.PrintPerimeter();
 4 
 5             //Shape circle = new Circle(10);
 6             //circle.PrintArea();
 7             //circle.PrintPerimeter();
 8             //Console.ReadKey();
 9             Shape[] shapes = new Shape[]
10             {
11                new Circle(10),
12                new Circle(8),
13                new Circle(100),
14                new Triangle(3,4,5),
15                new Triangle(10,10,10),
16                new Triangle(8,10,12)
17             };
18             foreach (Shape shape in shapes)
19             {
20                 Console.WriteLine("***********************************");
21                 shape.PrintArea();
22                 shape.PrintPerimeter();
23                 Console.WriteLine("***********************************");
24                 Console.WriteLine();
25             }
26             Console.ReadKey();
查看代码

PS:本篇博客只是我学习的理解和认识,希望对于刚学C#语言的朋友们理解继承、封装和多态有一定的帮助作用,有不对之处请评论告知!

posted @ 2012-01-06 18:50  JumpByte  阅读(914)  评论(1编辑  收藏  举报