C#面向对象

C#

浏览数:218

2019-4-3

AD:资源代下载服务

C#是面向对象的语言,所有面向对象的语言都具有三个基本的特征,它们是:封装:把客观事物封装成类,并将类内部实现隐藏,以保证数据的完整性。继承:通过继承可以复用父类的代码。多态:允许将子对象赋值给父对象的一种能力。C#中的面向对象编程指的是运用这三个基本的特征来编写程序。下面详细的介绍一下。

1.1 封装

封装指的是把类的内部实现隐藏起来,不让对象直接对其进行操作。C#提供了属性机制对内部的状态进行操作。在C#中,封装可以通过public,protected,private,internal来体现。为什么使用封装,因为有的时候,我们把内部的数据定义为public之后,外部对象可以进行任意的操作,很可能导致不符合逻辑规则。面向对象的封装特性,是一种保护状态数据完整性的方法,在面向对象编程中,应更多的定义私有字段,并且使用属性机制来对私有字段进行访问。下面代码演示了封装的具体操作。


1.2 继承

在C#中,一个类可以继承另外一个已有的类(密封类除外),被继承的类称为基类(或者父类),继承的类称为派生类,子类将获得基类除构造函数和析构函数以外的所有成员。此外,静态类也不能被继承。例如,牛马羊都是动物,但是它们是不同种类的动物,除了动物的共性外,它们还具有各自的特点,如不同的用途,不同的发声方式等。我们可以把动物定义为牛羊马的父类。通过继承,程序可以实现对父类代码的复用。因为子类可以继承父类的所有成员,父类中定义的代码便不需要在子类中重复定义了。


上述的代码之中,虽然子类并没有定义Age属性,但是由于它们都继承自Animal,基类中有Age属性,所有子类也就继承了父类的Age。需要注意的是,子类并不能对父类的的私有成员进行访问,它只能对保护成员或者公有成员进行访问。如果把上述代码中的Age属性定义为私有属性,则Main函数则不能直接对该属性进行赋值操作了。私有成员也会被子类继承,但是子类不能直接访问私有成员。子类可以通过调用公有或者保护方法间接的对私有成员进行访问。

1.2.1 密封类

密封类是指不能被继承的类,强行继承会产生编译错误。C#中使用sealed关键字来定义密封类,如下代码所示:


1.2.2 子类的初始化顺序

使用了继承之后,当我们初始化一个子类时,除了会调用子类的构造函数之外,同时也会调用基类的构造函数,子类的初始化顺序如下: 1:初始化类的实例字段 2:调用基类的构造函数,若没有基类,调用System.Object的构造函数。 3:调用子类的构造函数。下面通过一个例子演示调用顺序:

1.3 多态

由于可以继承基类的成员,子类就有了相同的行为,但是有时子类的某些行为需要相互区别。子类需要覆盖父类中的方法来实现子类特有的行为,这就是多态。多态即相同类型的对象调用相同的方法却表现出不同行为的现象。 1.3.1 使用virtual和override关键字实现方法重写

只有基类成员声明为virtual或者abstract时,才能被派生类重写;而子类想改变虚方法的实现行为,则必须使用override关键字。下面的代码演示了C#对多态的支持:



上述代码相同类型的对象调用相同的方法确实表现出了不同的行为,这就是多态的精髓。但是还存在一个问题,我们还是可以通过new操作符创建Animal基类的实例,可Animal基类的作用是为所有的子类提供公共成员,它是一个抽象的概念。我们希望它不能创建实例,怎么办? 我们可以使用abstract关键字防止在代码中直接创建这样的实例,正确代码如下所示:

1.3.2 阻止派生类重写虚成员

前面说过,用sealed关键字可以防止一个类被其它类继承。同样也可以使用sealed关键字来阻止派生类重写虚成员。例如,我们希望Horse的继承类不再扩展Voice方法,则可以使用sealed关键字来停止虚拟继承,如下代码所示:


1.3.3 使用新成员隐藏基类成员

如果想在派生类中定义与基类同名的成员,则可以使用new关键字把基类成员隐藏起来。如果不使用new关键字,在派生类中定义一个与基类成员同名的成员,编译器将产生警告。 在实际开发中,若确是需要添加某个方法,但是该方法又于基类的方法同名,那么刻意使用new关键字把基类成员隐藏。

如果仍然想访问基类成员,则可以使用强制类型转换,把子类强制转换为基类,从而访问隐藏的基类成员。

1.4 所有类的父类System.object

在C#中,所有的类都派生自System.Object,如果定义的类没有制定任何基类,编译器就会自动把Object当作基类。