智卓见

专注研究AI+全域运营
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

第二章:C#.NET面向对象——继承、多态与接口1(继承)

Posted on 2011-05-26 01:25  智卓见  阅读(3402)  评论(3)    收藏  举报

   当今的面向对象编程语言都提供了继承、多态和接口的功能,C#作为一种面向对象的高级编程评议也具有这样的特点。继承是面向对象语言的基本特征,是实现代码利用的手段。继承使得在原有类的基础之上,对原有的程序进行扩展,从面提高程序开发的速度,实现代码的复用。同一种方法作用于不同对象可以产生不同的结果,这就是多态。它是通过在基类中使用虚方法,在其派生类中使用重载实现的。

 

<一> 继承

在面向对象的编程中,经常用到一些相同特点的类,将相同特点提取就可以生成一个基类,其他类继承基类的成员,比如方法、属性等。不仅如此,派生类可以在继承的父类成员的基础上增加一些变量、方法和属性等。派生类也可以覆盖被继承的方兴未并且重写此方法。继承带来了实现代码复用。提高开发速度等优点。

 

1、使用继承

   继承是指这样的一种能力:它可以使用现有类的所有功能,并在无须重新编写原来的类的情况下对这些功能进行扩展。使用继承而产生的类被称为派生类或子类,而被继承的类则称为基类、超类或父类。

   在C#中,派生类从它的直接基类中继承成员:字段、属性、方法、事件、索引器。除了构造函数和析构耿,派生类隐式地继承了直接基类的所有成员。

   C#中的继承符合下列规则:

   ◆ 继承是可传递的。如果C从B派生,B又从A派生,那么C不仅继承了B中声明的成员,同样也继承了A中的成员。Object类作为所有类的基类。

   ◆ 派生类应当是对基类的扩展。派生类可以添加新的成员,但不能除去已经继承的成员的定义。

   ◆ 构造函数和析构函数不能被继承。除此以外的其他成员,不论对它们定义了怎样的访问方式都能被继承。基类中成员的访问方式只能决定派生类能否访问它们。

   ◆ 如果派生类定义了与基类成员同名的新成员,就可以重载或覆盖基类的成员。但这并不因为派生类而删除了这些成员,只是不能再访问这些成员。

   ◆ 类可以定义虚方法、虚属性以及虚索引器,它的派生类能够重载这些成员,从而实现类可以展示出多态性。另外,类也可以定义静态方法、静态属性和静态索引器。

   ◆ 派生类只能从一个类中继承,可以通过接口实现多重继承。

下面通过一个例子说明类的继承

using System;

using System.Collections;

namespace 笔记

{

    //定义基类

    public class Shape

    {

        protected string Color;

        public Shape()

        { ;}

        public Shape(string Color)

        {

            this.Color = Color;

        }

        public string GetColor()

        {

            return Color;

        }

    }

 

    //定义Circle类,从Shapte类中派生

    public class Circle : Shape

    {

        private double Radius;

        public Circle(string Color, double Radius)

        {

            this.Color = Color;

            this.Radius=Radius;

        }

        public double GetArea()

        {

            return System.Math.PI * Radius * Radius;

        }

    }

 

    //派生类Rectangular,从Shape类中派生

    public class Rectangular : Shape

    {

        protected double Length, Width;

        public Rectangular()

        {

            Length = Width = 0;

        }

        public Rectangular(string Color, double Length, double Width)

        {

            this.Color = Color;

            this.Length = Length;

            this.Width = Width;

        }

        public double AreaIs()

        {

            return Length * Width;

        }

        public double PerimeterIs() //周长

        {

            return (2 * (Length + Width));

        }

    }

 

    //派生类Square,从Rectangular类中派生

    public class Square : Rectangular

    {

        public Square(string Color, double Side)

        {

            this.Color = Color;

            this.Length = this.Width = Side;

        }

    }

 

    public class Test

    {

        public static void MMain()

        {

            Circle Cir = new Circle("Orange", 3.0);

            Console.WriteLine("圆的颜色是:{0},圆的面积是:{1}", Cir.GetColor(), Cir.GetArea());

            Rectangular Rect = new Rectangular("Red", 13.0, 2.0);

            Console.WriteLine("长方形颜色是:{0},长方形面积是:{1},长方形周长是:{2}", Rect.GetColor(), Rect.AreaIs(), Rect.PerimeterIs());

            Square Squ = new Square("Green", 5.0);

            Console.WriteLine("Square Color is {0},Square Area is {1},Square Perimeter is {2}", Squ.GetColor(), Squ.AreaIs(), Squ.PerimeterIs());

        }

    }

}

程序运行结果是:

圆的颜色是:Orange,圆的面积是:28.2743338823081

长方形颜色是:Red,长方形面积是:26,长方形周长是:30

Square Color is Green,Square Area is 25,Square Perimeter is 20

   基类Shape类直接派生了Circle和Rectangular类,Rectangular类又派生了Square类。因为基类的字段Color修饰符为protected以及方法GetColor修饰符为public,它们在派生类中都可使用。派生类在继承基类的成员基础上,也可以各自增加功能。

   如果一个派生类拥有两个以上的父类,则称为多重继承,如果仅有一个父类,则称为单继承。多重继承在使用程序语言实现时,会造成一些不必要的困扰,虽然C++中可以使用多重继承,但C#却不支持。C#虽然不支持多重继承,但是提供了另一种类似多重继承的机制——接口。

 

2、base关键字

 

(1)调用基类的构造函数

上例程序中的Square类也可以改写为:

 

    //派生类Square,从Rectangular类中派生

    public class Square : Rectangular

    {

        public Square(string Color, double Side)

            : base(Color, Side, Side)

        { ;}

    }

   关键字base的作用是调用Rectangular类的构造函数并将Square类的变量初始化。

(2)调用基类的方法

Base调用基类方法的例子:

using System;

using System.Collections;

namespace 笔记

{

    public class Person

    {

        protected string Phone = "13824128413";

        protected string Name = "刘德荣";

        public void GetInfoPerson()

        {

            Console.WriteLine("Phone:{0}", Phone);

            Console.WriteLine("Name:{0}", Name);

        }

    }

    class Employee : Person

    {

        public string ID = "5108060306";

        public void GetInfoEmployee()

        {

            //调用基类Person的GetInfoPerson方法

            base.GetInfoPerson();

            Console.WriteLine("Employee ID:{0}", ID);

        }

    }

    public class TestClass

    {

        public static void MMain()

        {

            Employee Emp = new Employee();

            Emp.GetInfoEmployee();

        }

    }

}

程序运行结果:

Phone:13824128413

Name:刘德荣

Employee ID:5108060306

3、继承中的构造函数与析构函数

   在前面讨论过,派生类的构造函数会隐式调用父类的无参构造函数。那么,如果父类也是派生于其他类,会是什么的情形呢?C#的执行顺序是这样的:根据层次链找到最顶层的基类,先调用基类的构造函数,再依次调用各级派生类的构造函数。而析构函数的次序正好相反。

   类一般不需要使用析构函数回收占用资源,而是由系统自动完成,这里使用析构函数的目的是为了更好了解构造函数和析构函数的执行过程。

 

4、System.Object类

   C#所有类都派生自System.Object类。在定义类时如果没有指定派生自哪一个类,系统就默认基派生自Objectod 。

   System.Object类常见的公有方法是:

   ◆ Equals:如果两个对象具有相同值时,方法返回true。

   ◆ GetHashCode:方法返回对象的散列码。

   ◆ ToString:通过在派生类中重写该方法,返回一个表示对象状态的字符串。