• 用一个简单示例来说明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#语言的朋友们理解继承、封装和多态有一定的帮助作用,有不对之处请评论告知!

  • 相关阅读:
    图形用户界面
    集合
    201671010136 泛型类总结
    异常、断言与日志
    [置顶]201671010131《面向对象程序设计课程学习进度条》
    [置顶]201671010131《面向对象程序设计课程学习进度条》
    201671010131《面向对象程序设计课程学习进度条》
    201671010131《面向对象程序设计课程学习进度条》
    201671010131《面向对象程序设计课程学习进度条》
    201671010131《面向对象程序设计课程学习进度条》
  • 原文地址:https://www.cnblogs.com/yja9010/p/3178780.html
Copyright © 2020-2023  润新知