多态的实现(重载,虚方法,抽象类,接口)
1.前言
多态是指,在同一个方法中,由于参数不同而导致执行效果各异。多态的实现方式主要是通过函数、运算符重载,虚成员,以及抽象类实现和接口。下面的内容就详细介绍一下前三种多态的实现形式。
2.方法重载
在同一作用域范围内,可以为同一个方法名声明多个定义,但是方法之间的定义必须不同,可以是参数列表的类型或个数的差异,但不可以重载只有返回类型不同的函数。下面的示例展示了如何实现方法的重载。
class Person {public void Show(){Console.WriteLine($"name: kyle");}public void Show(int age){Console.WriteLine($"name: kyle, age: {age}");} }class Program {static void Main(string[] args){Person p = new Person();p.Show();p.Show(23);Console.ReadKey();} }
输出结果如下:
name: kyle name: kyle, age: 23
常见的函数重载是对 Object 类中的 ToString()方法进行重载:
class Person {public string Name { get; set; }public int Age { get; set; }public override string ToString(){return "Person: " + Name + " " + Age;} }
其测试代码及结果如下:
Person person = new Person { Name = "John", Age = 12 }; Console.WriteLine(person); // Output: // Person: John 12
3.运算符重载
可以重定义或重载 C# 中内置的运算符,以此使用用户自定义类型的运算符。重载运算符是具有特殊名称的函数,是通过关键字 operator 后跟运算符的符号来定义的。与其他函数一样,重载运算符有返回类型和参数列表。
下面的代码演示了运算符 + 的重载:
class Box {double length;double width;public Box(double l, double w){length = l;width = w;}public double Area(){return length * width;}public static double operator + (Box box1, Box box2){return box1.Area() + box2.Area();} }class Program {static void Main(string[] args){Box b1 = new Box(2.3, 1.2);Box b2 = new Box(4.4, 2.6);double total = b1 + b2;Console.WriteLine($"total area is {total}");Console.ReadKey();} }
输出结果如下:
total area is 14.2
3.虚成员
3.1 override重写
当派生类从普通基类继承时,它会获得基类的所有公开方法、字段、属性和事件,当基类的成员声明为 virtual 时,派生类还可以对基类的成员(除字段)进行重写。在进行成员的重写时,派生类中需使用 override 关键字显示成员的重写。
下面的代码展示了对基类中的虚成员的重写:
public class BaseClass {public virtual void DoWork() { }public virtual int WorkProperty{get { return 0; }} }public class DerivedClass : BaseClass {public override void DoWork() { }public override int WorkProperty{get { return 0; }} }
在使用 override 重写虚成员时,会对基类中的虚方法的覆盖,因此即便将派生类的示例转为基类的实例,仍会调用重写后的新成员,调用过程及结果如下:
DerivedClass B = new DerivedClass(); B.DoWork(); // Calls the new method. BaseClass A = (BaseClass)B; A.DoWork(); // Also calls the new method.
3.2 使用新成员隐藏基类成员
如果不希望覆盖掉基类中的既有虚成员,可以通过 new 关键字(默认),从而禁止派生类参与基类的虚成员调用。
以下代码展示了如何使用新成员来隐藏基类成员,而不是重写覆盖:
public class BaseClass {public void DoWork() { WorkField++; }public int WorkField;public int WorkProperty{get { return 0; }} }public class DerivedClass : BaseClass {public new void DoWork() { WorkField++; } // 不覆盖基类虚方法public new int WorkField;public new int WorkProperty{get { return 0; }} }
在使用 new 关键字重写虚成员后,如果将派生类的实例转换为基类的实例,将会调用基类原有的虚成员,调用过程及结果如下:
DerivedClass B = new DerivedClass(); B.DoWork(); // Calls the new method. BaseClass A = (BaseClass)B; A.DoWork(); // Calls the old method.
3.3 阻止派生类重写虚成员
在类的继承过程中,虚成员默认始终保持其虚拟性(因此 override 关键字声明的重写成员也具有虚拟性),如果希望停止其虚拟继承,可以将虚成员声明为 sealed 来实现,其实现代码如下:
public class A {public virtual void DoWork() { } } public class B : A {public override void DoWork() { } }public class C : B {public sealed override void DoWork() { } }
在使用 sealed 声明虚成员之后,有 C 继承而来的类中的 Dowork() 不再保留虚拟性,但对于 C 的实例而言仍旧是虚拟的。C 的派生类可以通过 new 关键字最后重写 C 中的 Dowork() :
public class D : C {public new void DoWork() { } }
3.4 在派生类中访问基类虚成员
如果要在派生类中直接访问基类的虚成员,可以使用 base 关键字进行访问,示例代码如下:
public class Base {public virtual void DoWork() {/*...*/ } } public class Derived : Base {public override void DoWork(){//Perform Derived's work here//...// Call DoWork on base classbase.DoWork();} }
4.抽象类
通过 abstract 关键字声明一个抽象类,例如:
public abstract class A {// Class members here. }
抽象类不可以进行实例化,其作用是作为一个可供多个派生类继承的通用基类。在抽象类中可以定义字段、属性、方法等,还可以通过关键字 abstract 添加到方法的返回类型前定义一个抽象方法,例如:
public abstract class A {public int name;public string Show(){return "string"; }public abstract void DoWork(int i); }
抽象方法没有实现,抽象类的派生类必须实现所有的抽象方法。当抽象类从基类继承虚方法时,抽象类也可以使用抽象方法重写虚方法,例如:
public class D {public virtual void DoWork(int i){// Original implementation. } }public abstract class E : D {public abstract override void DoWork(int i); }public class F : E {public override void DoWork(int i){// New implementation. } }
继承抽象方法的类无法访问方法的原始实现,即类 F 上的实例无法调用 D 中的 DoWork() ,通过这种方式,抽象类可强制派生类向虚拟方法提供新的方法实现。
由于抽象类需要作为基类由派生类继承,所以,抽象类无法使用 sealed 关键字和 static 关键字进行声明。
转载于:https://www.cnblogs.com/jizhiqiliao/p/9809480.html
多态的实现(重载,虚方法,抽象类,接口)相关推荐
- 浅谈C# 多态的魅力(虚方法,抽象,接口实现) ----转
浅谈C# 多态的魅力(虚方法,抽象,接口实现) 2013-06-15 0 个评论 作者:做一个别人眼中的好人 收藏 我要投稿 前言:我们都知道面向对象的三大特性:封装,继承 ...
- C#中实现多态的三种方式:抽象类,虚方法,接口
Interface(接口):是一种规则,要求继承类必需实现所有声明的成员,方法是公开的. Virtual方法(虚方法):可以在继承类里 Override覆盖重新的方方法,有自己的方法体.派生类可使用, ...
- 抽象类,虚方法,接口
这三样很多人容易混淆,在此总结一下 1. 虚方法 Virtual 基类中定义了虚方法,派生类中可以实现,也可以不实现,因为虚方法是有方法体的,如果要实现,派生类中用override重写该方法. pub ...
- C#多态性的小记,父类,子类,虚方法,接口
一.父类,子类的继承和虚方法重写 class Program{static void Main(string[] args){Person objperson= new Person ();//实例p ...
- c# 多态实现_虚方法
实现方法: 虚方法, 抽象类, 接口 1.虚方法 将父类的方法标记为虚方法,使用关键字virtual,这个方法可以被子类重新写一遍. 在父类的方法前面加上一个virtual,在子类的方法前面加上一个o ...
- 多态的两种种实现方式(虚方法,抽象类)
今天有又是苦逼的一天,准备考研,但是英语是真拉,废话不多开始今天主题--多态 多态 前言 一.虚方法 语法 二.抽象类 语法 实例 无方法和空实现 抽象类的特点 抽象类和虚方法的区别及各自使用时机 区 ...
- 什么情况下会用到虚方法(虚函数)?它与接口有什么不同?
面试的时候遇到有这么一题:您在什么情况下会用到虚方法(虚函数)?它与接口有什么不同? 当不同的人面对这个问题的时候应该是有不同的反应,因为每个人对以上提到的知识点的理解程度不同.绝对有人迷惑,也有人似 ...
- C#类、接口、虚方法和抽象方法-虚拟方法与抽象方法之区别
虚方法和抽象方法都可以供派生类重写,它们之间有什么区别呢? 1. 虚方法必须有实现部分,并为派生类提供了重写该方法的选项.抽象方法没有提供实现部分,抽象方法是一种强制派生类重写的方法,否则派生类将不能 ...
- C#类和接口、虚方法和抽象方法及值类型和引用类型的区别
1.C#类和接口的区别 接口是负责功能的定义,项目中通过接口来规范类,操作类以及抽象类的概念! 而类是负责功能的具体实现! 在类中也有抽象类的定义,抽象类与接口的区别在于: 抽象类是一个不完全的类,类 ...
最新文章
- WindowsServer2003双网卡配置
- js——页面回到顶部
- .NET三种事务处理详解
- my current understanding of learning and graduate studies
- Linux:多进程、多线程服务器的实现解析(有图有代码有真相!!!)
- 使用T—SQL语句操作数据库
- Android Studio 修改项目包名(任意级)
- 实习成长之路:操作系统——CPU有哪些工作模式呢?
- 高性能 Windows Socket 服务端与客户端组件(HP-Socket v1.0.1 源代码及测试用例下载)...
- 给MDK5/KEIL5安装51/ARM编译坏境
- 什么是黑链?什么是黑帽?什么是明链?
- 《java websocket》之 实现
- 通过阅读饥荒代码理解树人机制
- java渗透_java 渗透模型
- 学java开发需要什么配置的电脑?
- 智能音箱里小度、小爱、天猫精灵哪个更加好?(下)
- 如何拆笔记本--键盘拆卸
- 在土豆传的第一篇视频
- 微信小程序云开发之收藏文章功能的简单实现
- RTP/RTSP/RTCP 协议详解