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

多态的实现(重载,虚方法,抽象类,接口)相关推荐

  1. 浅谈C# 多态的魅力(虚方法,抽象,接口实现) ----转

    浅谈C# 多态的魅力(虚方法,抽象,接口实现) 2013-06-15      0 个评论       作者:做一个别人眼中的好人 收藏    我要投稿 前言:我们都知道面向对象的三大特性:封装,继承 ...

  2. C#中实现多态的三种方式:抽象类,虚方法,接口

    Interface(接口):是一种规则,要求继承类必需实现所有声明的成员,方法是公开的. Virtual方法(虚方法):可以在继承类里 Override覆盖重新的方方法,有自己的方法体.派生类可使用, ...

  3. 抽象类,虚方法,接口

    这三样很多人容易混淆,在此总结一下 1. 虚方法 Virtual 基类中定义了虚方法,派生类中可以实现,也可以不实现,因为虚方法是有方法体的,如果要实现,派生类中用override重写该方法. pub ...

  4. C#多态性的小记,父类,子类,虚方法,接口

    一.父类,子类的继承和虚方法重写 class Program{static void Main(string[] args){Person objperson= new Person ();//实例p ...

  5. c# 多态实现_虚方法

    实现方法: 虚方法, 抽象类, 接口 1.虚方法 将父类的方法标记为虚方法,使用关键字virtual,这个方法可以被子类重新写一遍. 在父类的方法前面加上一个virtual,在子类的方法前面加上一个o ...

  6. 多态的两种种实现方式(虚方法,抽象类)

    今天有又是苦逼的一天,准备考研,但是英语是真拉,废话不多开始今天主题--多态 多态 前言 一.虚方法 语法 二.抽象类 语法 实例 无方法和空实现 抽象类的特点 抽象类和虚方法的区别及各自使用时机 区 ...

  7. 什么情况下会用到虚方法(虚函数)?它与接口有什么不同?

    面试的时候遇到有这么一题:您在什么情况下会用到虚方法(虚函数)?它与接口有什么不同? 当不同的人面对这个问题的时候应该是有不同的反应,因为每个人对以上提到的知识点的理解程度不同.绝对有人迷惑,也有人似 ...

  8. C#类、接口、虚方法和抽象方法-虚拟方法与抽象方法之区别

    虚方法和抽象方法都可以供派生类重写,它们之间有什么区别呢? 1. 虚方法必须有实现部分,并为派生类提供了重写该方法的选项.抽象方法没有提供实现部分,抽象方法是一种强制派生类重写的方法,否则派生类将不能 ...

  9. C#类和接口、虚方法和抽象方法及值类型和引用类型的区别

    1.C#类和接口的区别 接口是负责功能的定义,项目中通过接口来规范类,操作类以及抽象类的概念! 而类是负责功能的具体实现! 在类中也有抽象类的定义,抽象类与接口的区别在于: 抽象类是一个不完全的类,类 ...

最新文章

  1. WindowsServer2003双网卡配置
  2. js——页面回到顶部
  3. .NET三种事务处理详解
  4. my current understanding of learning and graduate studies
  5. Linux:多进程、多线程服务器的实现解析(有图有代码有真相!!!)
  6. 使用T—SQL语句操作数据库
  7. Android Studio 修改项目包名(任意级)
  8. 实习成长之路:操作系统——CPU有哪些工作模式呢?
  9. 高性能 Windows Socket 服务端与客户端组件(HP-Socket v1.0.1 源代码及测试用例下载)...
  10. 给MDK5/KEIL5安装51/ARM编译坏境
  11. 什么是黑链?什么是黑帽?什么是明链?
  12. 《java websocket》之 实现
  13. 通过阅读饥荒代码理解树人机制
  14. java渗透_java 渗透模型
  15. 学java开发需要什么配置的电脑?
  16. 智能音箱里小度、小爱、天猫精灵哪个更加好?(下)
  17. 如何拆笔记本--键盘拆卸
  18. 在土豆传的第一篇视频
  19. 微信小程序云开发之收藏文章功能的简单实现
  20. RTP/RTSP/RTCP 协议详解

热门文章

  1. 中国发电机行业应用前景与投资策略分析报告2022版
  2. 《软件工程》第01章在线测试
  3. java类编译_java类编译过程
  4. 十大最急需IT技术人才榜:Java开发人员领跑
  5. 你还笃信亲身经历的事情吗?来看看大脑如何处理感觉信息
  6. 初级和高级产品运营的分水岭指标:大局观和节奏感
  7. 应届生,你凭什么认为你当得了产品经理?| PMCAFF
  8. PMCAFF | 用户体验中4个你不曾知晓的秘密
  9. Ubuntu 编译安装python3.7
  10. 使用阿里云ACM简化你的Spring Cloud微服务环境配置管理 1