【C#】之 封装、继承与多态

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/molihuakai_118/article/details/81874005

我们知道封装、继承和多态是面向对象方法设计中的三大基本特性,下面将具体讲解这三个特性的具体表现及意义。

#一、封装

##1、说明

  从字面意思上看,封装就是打包的意思,将什么包装起来,专业一点就是信息的隐藏,将对象的属性和方法打包成一个相对独立的单位,尽可能隐蔽对象的内部细节,对外形成一个边界,若有其他类或方法想访问这个被封装了的类,需要通过接口来实现,即对外有函数作为通道,对内有变量作为原料。

  对象安全性的高低取决于其封装的程度,我们在声明属性方法时,会有public、private、protected、internal等访问修饰符,这些修饰符就定义了访问的级别,从而也就决定了封装的程度。

		public——公共成员,完全公开,没有访问限制
		private——私有成员,在类的额内部才可以访问
		protected——保护成员,该类内部和继承类(子类) 中可以访问
		internal——当前程序集内可以访问,类的默认访问修饰符

##2、为什么要封装
  可以说,在任何程序中,我们无时无刻都在运用封装这一特性,那么我们为甚么这么频繁的使用封装呢?

  当对象被创建时,如果没有被封装,即可以通过对象的引用获取任意成员的属性值,并能够给所有的成员属性任意赋值。这样是非常危险的,第一,对象中的成员属性是对象本身的特有属性,如果很轻易的被其他对象访问并修改,那这些属性存的意义就没有了。第二,对象中的成员方法只有部分是给外部提供的,有些是对象自己使用的方法,如果外部能够随意调用对象内部的所有方法,这个方法存在也就没有意义了。

  举个例子,在”人”的对象中,提供了”走路”的方法,而”走路”的方法又是通过在对象内部调用”迈左腿”和” 迈右腿”两个方法组成。如果用户在对象的外部直接调用” 迈左腿”或” 迈右腿”的方法就没有意义,应该只让用户能调用”走路”的方法。

  有了封装,我们就能够有效的避免外部错误对内部造成的“交叉感染”,使软件错误能够局部化。

封装好处:

 1、良好的封装能够减少耦合。

2、类内部的结构可以自由修改。

3、可以对成员进行更精确的控制。

4、隐藏信息,实现细节。

#二、继承

##1、说明

  继承是父与子的关系,当代码中需要申请多个类或多个方法时,如果这些类或方法有一定相同的属性,为了减少代码的冗余,可以使用继承关系,减少代码量。

  子类或子函数可以继承父类或父函数中的所有属性,父类中含有所有子类的共同特征。在主函数中为子类或子方法赋值时,可以直接调用父类或父方法中的属性。

##2、构造函数中的继承
  之前我们有说过构造函数,他其实就是在一定程度上改变了封装对象接口的类型,不仅减少了代码量,而且增加了被访问对象的安全性。那么如果两个类或方法存在继承关系,在其中使用构造函数时,我们需要注意哪些呢?

  由于子类中属性可能比较多,需要利用到有参的构造函数,当子类在实例化时,会调用父类无参的构造函数来得以实现。但是类都可以实例化,父类也不例外,当父类也利用有参构造函数实例化时,就会覆盖了原来的无参的构造函数(类中都会默认有一个无参的构造函数),从而导致子类的实例化无法实现,所以此时可以再在父类中建立一个无参的构造函数来供子类的调用。

  那么如果子类中有参的构造函数与父类中有参的构造函数有相同的参数,能不能直接通过子类有参的构造函数调用父类有参的构造函数来减少代码的输入量呢?答案是肯定的,这是就用到了base,在子类构造函数后面加上“:base(相同的参数类型)

这里写图片描述
这里写图片描述
这里写图片描述

#三、多态

##1、说明

多态

通俗来讲:就是对象能够表现多个类型的能力。
比较全面的说法:就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。我们不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序选择多个运行状态,这就是多态。

好吧,举个例子:
  我们定义动物这个类,他有“颜色”属性,有“叫”这个方法,但是如果将动物实例化,比如猫,狗,老鼠等,他们都各自有各自的颜色属性值和叫的方法值。这些都需要在运行期间才能决定,这样在运行期间让程序选择多个运行状态,就是多态。

##2、实现形式
###1>接口
  接口是多态的体现形式,用 Interface 来定义,语法如下:

	 [访问修饰符] interface 接口名
			{
				//接口成员定义
			}

说明:
接口不能直接实例化
接口中没有方法体的实现
类似于抽象基类,继承接口的任何非抽象类型都必须实现接口的所有成员
接口之间支持多重继承,但是类不能,类只有一个父类

###2>重写

  子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。

  重写时,子类的方法名和父类的方法名重名,但是子类方法名下会出现一条绿线(不影响使用)

解决绿线方法:
1、可以在子类方法的修饰符后面加new,隐藏父类方法(无论是否加new都不影响使用)
2、可以在父类的方法的修饰符后面加virtual(变成虚方法),在子类的方法的修饰符后面加override(使子类重写父类方法,变成实的),在子类的方法中可以直接使用父类方法也可以重新赋值。

作用:
  如果我们执行一个操作:申请很多类,将这些类放到集合当中,遍历这个集合的时候,把这些类中的方法全部调用出来。
  如果没有重写,我们就需要一个个判断子类父类能不能转换,然后一个个调用方法。如果有了重写,我们只需要判断子类父类能不能转换,然后再最后调用一个方法就可以了,因为名字相同,只要一个方法调用就可以,内容可以重新覆盖。

###3>抽象方法与抽象类

  子类能够继承父类的一些属性方法,但是很多子类对于父类的这个方法可能有很多不同的值,这时就可以不将父类中的这个方法定死,即写一个抽象类,将这个方法变成抽象方法,在子类中调用这个抽象方法并重写,这样就实现了子类继承父类的特有的方法值。

规则:

	抽象用abstract来修饰
	抽象方法没有方法体
	抽象方法必须在抽象类当中
	抽象类只能用作基类,无法实例化 
	抽象类中可以有非抽象成员
	抽象类的派生类必须实现抽象方法体
	父类是抽象类,子类继承了这个类,必须把抽象类中的抽象方法重写

猜你喜欢

转载自blog.csdn.net/molihuakai_118/article/details/81874005
今日推荐