c#基础语言编程-多态
语言中的多态性是为了使程序有扩展性,为实现多态性,在程序中体现为接口、抽象类、父类、具体类。
接口就是一种规范,解决了多重继承的问题,类似一种规范,告诉我要做什么,具有什么能力,在接口中定义写行为属性。
接口的特性
- 接口类类似抽象类,不能实例化接口;接口中的方法都是抽象方法,继承于此接口的非抽象类必须实现接口中所有成员。
- 接口只能包含方法(属性、事件、索引器最终都是方法),不能有字段、常量、构造函数和析构函数、静态变量,但是可以有委托和事件。
- 接口中成员不许有访问修饰符,默认为public,手动添加会编译出错。 接口中成员只有定义,没有任何实现,像抽象类一样
- 实现接口的类,直接实现接口中的方法,不用写override。
- 当显示该接口的成员时,实例成员不能通过类实例访问(不提倡用类实例访问,这样就无法体现多态性),只能通过接口实例访问,显示实现默认是private。当隐示实现接口成员,两者实例都能访问,但是要将成员表示为public。
比如:
public class Person : IFace1, IFace2
{
public void Fly()
{
Console.WriteLine("实现了IFace1中的Fly方法。");
}
//显示实现接口的访问修饰符默认是没有的,类中成员没有写访问修饰符这默认就是private
//显示实现接口是私有的所以必须通过接口名才能访问的到。
void IFace2.Fly()
{
Console.WriteLine("实现了IFace2中的Fly方法。");
}
}
public interface IFace1
{
void Fly();
}
public interface IFace2
{
void Fly();
}
Person p = new Person();
p.Fly();//face1中的Fly()face2中显示实现,为private,通过new Person 无法获取到。
IFace1 f1 = new Person();
f1.Fly();//face1中的Fly()
IFace2 f2 = new Person();
f2.Fly();//face2中的Fly()
virtual和override的应用
virtual是虚函数的关键词,override是重写的关键词。有virtual关键词,意味允许继承者可以用override重写。如果不用override,则不是重写。
例如:
class Person
{
public virtual void Introduce()
{
Console.WriteLine("我是来自地球");
}
}
class Chinese : Person
{
public override void Introduce()
{
Console.WriteLine("我的户口,身份证号码");
}
}
class American : Person
{
//此处没有加override,所以在后续代码中无法调用此方法。
public void Introduce()
{
Console.WriteLine("社会保险号:00000");
}
}
Person p1 = new Chinese();
p1.Introduce();
Person p2 = new American();
p2.Introduce();
显示的结果为:我的户口,身份证号码。我是来自地球
当一个抽象类实现接口的时候,如果不想把接口成员实现,可以把成员实现为abstract。
为什么不能指定接口中方法的修饰符?
接口中的方法用来定义对象之间通信的契约,指定接口中的方法为私有或保护没有意义。它们默认为公有方法。
抽象类
抽象类是包含抽象方法的类。那么什么又是抽象方法呢?抽象方法是没有方法内容的,只有一个方法名和参数列表的方法。并以;结尾。为了标注他的与众不同,在他的返回类型前加abstract。并在class前加abstract。
简言之,由abstract修饰的方法和类就是抽象的方法和类。
//抽象状态类State,定义一个接口以封装与Context的一个特定状态相关的行为
abstract class State
{
public abstract void Handle(Context context);
}
//ConcreteState类,具体状态,每一个子类实现一个与Context的一个状态相关的行为
class ConcreteStateA : State
{
public override void Handle(Context context)
{
//设置ConcreteStateA的下一个状态是ConcreteStateB
context.State = new ConcreteStateB();
}
}
class ConcreteStateB : State
{
public override void Handle(Context context)
{
//设置ConcreteStateB的下一个状态是ConcreteStateA
context.State = new ConcreteStateA();
}
}
抽象类不能实例化,必须通过继承由派生类实现其抽象方法,因此对抽象类不能使用new关键字,也不能被密封。如果派生类没有实现所有的抽象方法,则该派生类也必须声明为抽象类。另外,实现抽象方法由override方法来实现。
接口与抽象类的相同点:
1、不能实例化;
2、包含未实现的方法声明;
3、派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括其他成员);
接口和抽象类的区别
1.类是对对象的抽象,可以把抽象类理解为把类当作对象,抽象成的类叫做抽象类.而接口只是一个行为的规范或规定
2.接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法;
3.一个类一次可以实现若干个接口,但是只能扩展一个父类
4.接口可以用于支持回调,而继承并不具备这个特点.
5.抽象类不能被密封。
6.抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的,当然您也可以声明为虚的.
7.(接口)与非抽象类类似,抽象类也必须为在该类的基类列表中列出的接口的所有成员提供它自己的实现。但是,允许抽象类将接口方法映射到抽象方法上。
8.抽象类实现了oop中的一个原则,把可变的与不可变的分离。抽象类和接口就是定义为不可变的,而把可变的座位子类去实现。
9.好的接口定义应该是具有专一功能性的,而不是多功能的,否则造成接口污染。如果一个类只是实现了这个接口的中一个功能,而不得不去实现接口中的其他方法,就叫接口污染。
10.尽量避免使用继承来实现组建功能,而是使用黑箱复用,即对象组合。因为继承的层次增多,造成最直接的后果就是当你调用这个类群中某一类,就必须把他们全部加载到栈中!后果可想而知.(结合堆栈原理理解)。同时,有心的朋友可以留意到微软在构建一个类时,很多时候用到了对象组合的方法。比如asp.net中,Page类,有Server Request等属性,但其实他们都是某个类的对象。使用Page类的这个对象来调用另外的类的方法和属性,这个是非常基本的一个设计原则。
11.如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法.
12. 接口定义方法,不能实现,而抽象类可以实现部分方法。
13.接口中基本数据类型为static 而抽类象不是的。
抽象类的功能要远超过接口,但是,定义抽象类的代价高。因为高级语言来说(从实际设计上来说也是)每个类只能继承一个类。在这个类中,你必须继承或编写出其所有子类的
所有共性。虽然接口在功能上会弱化许多,但是它只是针对一个动作的描述。而且你可以在一个类中同时实现多个接口。在设计阶段会降低难度的。
如何理解抽象类和接口
1.飞机会飞,鸟会飞,他们都继承了同一个接口“飞”;但是F22属于飞机抽象类,鸽子属于鸟抽象类。
2.就像铁门木门都是门(抽象类),你想要个门我给不了(不能实例化),但我可以给你个具体的铁门或木门(多态);而且只能是门,你不能说它是窗(单继承);一个门可以有锁(接口)也可以有门铃(多实现)。门(抽象类)定义了你是什么,接口(锁)规定了你能做什么(一个接口最好只能做一件事,你不能要求锁也能发出声音(接口污染))。
什么时候用接口实现多态?
答:当多个类型不能抽象出合理的父类时,但是又要对一些方法进行多态,此时可以考虑用接口。讲公共的方法抽象到一个接口中。
程序设计的原则(自己听课的结果)
- 接口》抽象类》父类》具体类(在定义方法参数、。返回值、声明变量的时候能使用抽象就不要使用具体参数。
- 能使用接口就不要使用抽象类,能使用抽象类就不要用类,能用父类就不要用子类。
- 避免使用”体积庞大的接口“”多功能接口“会造成接口污染。
- 单一职责、开放封闭、里氏替换、接口隔离、依赖接口
c#基础语言编程-多态的更多相关文章
- c#基础语言编程-装箱和拆箱
引言 为什么有装箱和拆箱,两者起到什么作用?NET的所有类型都是由基类System.Object继承过来的,包括最常用的基础类型:int, byte, short,bool等等,就是说所有的事物都是对 ...
- c#基础语言编程-程序集和反射
程序集 什么是程序集? 1.程序集(assembly)是一个及一个以上托管模块,以及一些资源文件的逻辑组合. 2.程序集是组件复用,以及实施安全策略和版本策略的最小单位. 3.程序集是包含一个或者多个 ...
- c#基础语言编程-正则表达式应用
引言 在不同语言中虽正则表达式一样,但应用函数还是有所区别,在c#语言中使用Regex. 可以通过以下两种方式之一使用正则表达式引擎: 通过调用 Regex 类的静态方法. 方法参数包含输入字符串和正 ...
- c#基础语言编程-正则表达式基础
引言 正则表达式是一种用高度抽象的字符串来描述字符串特征,进而实现对字符串的匹配.提取.替换等等.正则表达式(以下简称正则,Regex)通常不独立存在,各种编程语言和工具作为宿主语言提供对正则的支持, ...
- c#基础语言编程-文件流操作
引言 在System.IO 命名空间下提供了一系列的类,我们可以通过相应的类进行文件.目录.数据流的操作. 1.File类:提供用于创建.复制.删除.移动和打开文件的静态方法.File类 2.File ...
- c#基础语言编程-编码
字符编码是计算机技术的基础理论,其字符编码有ASCII码.UTF-8.还有就是GB2312,当然这是在中国常用的. 1.ASCII码 在计算机内部所有的信息都是以二进制字符进行存储.用每个二进制位中的 ...
- c#基础语言编程-Path和Directory
引言 在程序常会对文件操作,在对文件操作中需要对文件路径的进行定位,在.Net中针对寻找文件提供两个静态类以供调用,Path和Directory. Path类 来自命名空间SYstem.IO,Path ...
- c#基础语言编程-序列化
引言 程序员在编写应用程序的时候往往要将程序的某些数据存储在内存中,然后将其写入某个文件或是将它传输到网络中的另一台计算机上以实现通讯.这个将程序数据转化成能被存储并传输的格式的过程被称为" ...
- c#基础语言编程-集合
引言 在c#常用的集合分为非泛型集合和泛型集合. 非泛型集合的类和接口位于System.Collections命名空间.这些接口和类定义各种对象(如列表.队列.位数组.哈希表和字典)的集合. 泛型集合 ...
随机推荐
- C++ 虚函数与纯虚函数
#include<iostream> #include<string> using namespace std; class A{ public: virtual void f ...
- windows下node.js+sublime中安装coffeescript
node.js中安装Coffeescript 1.我的node.js安装目录 2.node.js 全局模块所在目录 3.node.js安装coffeescript npm install -g c ...
- Python 手册——开胃菜
如果你写过大规模的Shell脚本,应该会有过这样的体会:你还非常想再加一些别的功能进去,但它已经太大. 太慢.太复杂了:或者这个功能需要调用一个系统函数,或者它只适合通过C来调用……通常这些问题还不足 ...
- Pyqt5 实时图像滚动
实时图像 写了一个关于实时图像滚动显示的例子,做个记录. 滚动算法: 难点: 将内存数据绘制到界面,需要用到QImage和QPixmap,使用QImage转换一下,具体参见代码.这个费了好大劲才弄出来 ...
- decimall类型数据
同样是decimal(18,5) 和 decimal(18,4) 在VB中经过几次转化过后,数据就有可能改变. 遇到的情况 decimal(18,5)到 decimal(18,4)转换过程中数 ...
- 64位Win7下编译Python3的计算机视觉库:OpenCV
注:本文全原创,作者:Noah Zhang (http://www.cnblogs.com/noahzn/) OpenCV目前最新版是3.0.0 rc1,官方给出了编译好的Python2可以直接使用 ...
- objective-C: nonatomic retain copy assgin 等属性详解
http://my.oschina.net/u/728866/blog/90798 property,可以提供的功能有:提供成员变量的访问方法的声明.控制成员变量的访问权限.控制多线程时成员变量的访问 ...
- [转]hive中order by,distribute by,sort by,cluster by
转至http://my.oschina.net/repine/blog/296562 order by,distribute by,sort by,cluster by 查询使用说明 1 2 3 4 ...
- LightOj_1284 Lights inside 3D Grid
题目链接 题意: 给一个X * Y * Z 的立方体, 每个单位立方体内都有一盏灯, 初始状态是灭的, 你每次操作如下: 1)选择一个点(x1, y1, z1) 再选择一个点(x2, y2, ...
- pageControl设置不居中显示,居左或居右
UIPageControl控件,默认是居中显示的,如下图: 在很多的APP中,会看到pageControl是居左或居右显示的,如下图: 如何控制pageControl的位置显示呢? 设置为居右的代 ...