C#类的多态性详解

第一种:编译时的多态性,直接这样说不知道说啥?程序执行过程主要分为三步:编译,链接,运行。在编译时体现的多态性是通过方法的重载来实现的。方法的重载我们听过,就是一个类对象调用若干同名,但参数类型、个数不同。类对象是根据参数类型,个数来决定调用哪个同名方法,实现何种操作。C#语言的方法重载与C++、java基本是一样的,但是C#还包含C++的运算符重载,java里面没有这个概念。
第二种:运行时的多态性,是在系统运行时,调用一个名字相同,参数类型也相同以及个数也完全一样的方法,但会完成不同的操作。C#运行时的多态性通过虚方法实现。在类方法声明加上了virtual修饰符,称为虚方法,反之为非虚方法。就这一点C#跟C++有很多相似之处。
代码清单:虚方法与非虚方法的区别

namespace e_11
{
 class A
 {
  public void F()   //非虚方法
  { Console.WriteLine("A.F"); }
  public virtual void G() //虚方法
  { Console.WriteLine("A.G"); } 

 }
 class B : A     //A类为B类的基类
 {
  new public void F()  //隐藏基类的同名非虚方法F(),注意使用new
  { Console.WriteLine("B.F"); }
  public override void G() //隐藏基类的同名虚方法G(),注意使用override
  { Console.WriteLine("B.G"); }
 }
 class Test
 {
  static void F2(A aA)  //注意,参数为A类引用变量
  { aA.G(); }
  static void Main(string[] args)
  {
   B b = new B();
   A a1 = new A();
   A a2 = b;   //允许基类引用变量引用派生类对象,a2引用A类的派生类B的对象b
   a1.F();    //调用基类A的非虚方法F(),显示A.F
   a2.F();    //F()为非虚方法,调用基类A的F(),显示A.F
   b.F();    //F()为非虚方法,调用派生类的F(),显示B.F
   a1.G();    //G()为虚方法,因a1引用基类A对象,调用基类A的G(),显示A.G
   a2.G();    //G()为虚方法,因a2引用派生类B对象,调用派生类B的G(),显示B.G
   F2(a2);    //由于a2引用A类派生类B的对象b,调用派生类B的的G(),显示B.G
   F2(a1);    //实参为基类A对象,调用A类的函数G(),显示A.G
  }
 }
}
 

输出结果:

看上面的代码,我产生了一个疑问?为什么因为G()为虚方法,a2引用派生类B对象,调用的是B类的G()?
这里有一个解释:如果将基类引用变量引用不同对象,或者是基类对象,或者是派生类对象,用这个基类引用变量分别调用同名虚方法,根据对象的不同,会完成不同的操作。而非虚方法不具备次此功能。
关于类的多态性典型的例子:

//类的多态性
namespace e_11
{
 public class Person
 {
  private String name = "张三";   //类的成员说明
  private int age = 12;
  protected virtual void Display()  //类的虚方法
  { Console.WriteLine("姓名:{0},年龄:{1}", name, age); }
  public Person(string Name, int Age)  //构造函数,函数名和类名同名,无返回值
  { name = Name; age = Age; }
  static public void DisplayData(Person aPerson) //静态方法
  { aPerson.Display(); }    //不是静态方法调用实例方法,如写为Display()错误
 } 

 public class Employe : Person   //基类是Person
 {
  private string department;
  private decimal salary;
  public Employe(string Name, int Age, string D, decimal S)
   : base(Name, Age)
  { department = D; salary = S; }
  protected override void Display()  //重载虚方法,注意用Override
  {
   base.Display();
   Console.WriteLine("部门:{0}, 薪金:{1}", department, salary);
  }
 } 

 class Class1
 {
  static void Main(string[] args)
  {
   Person OnePerson = new Person("李四", 30);
   Person.DisplayData(OnePerson);  //显示基类的数据
   Employe OneEmployee = new Employe("王五", 40, "财务", 2000);
   Person.DisplayData(OneEmployee); //显示派生类数据
  }//两次调用完全相同的方法,实参不同,实现的功能不同
 } 

}

运行效果:

以上就是本文的全部内容,希望能够帮到大家。

(0)

相关推荐

  • C#操作ftp类完整实例

    本文实例讲述了C#操作ftp类.分享给大家供大家参考.具体如下: using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Net; using System.Globalization; namespace FtpTest1 { public class FtpWeb { string ftpServerIP; string ftpRemotePath; st

  • C#编程自学之类和对象

    在之前的文章中介绍了C#是一种完全面向对象的语言,既然是完全面向对象的语言就应该用面向对象的模式去学习C#,不了解面向对象?不必担心.这篇文章将介绍学习C#基础部分所要用到的面向对象的知识,后面文章我们将系统的介绍C#面向对象编程.接下来就开始我们C#旅程的起点! 一.类与对象 1 什么是类? 在我们现实世界中,我们经常会把具有一系列相同行为和属性的事物归类,例如:人类,人类就是我们所说的类.         例如 所有的人都有五官,内脏等等(除其他特殊原因),这些组成部分我们称之为人类的属性.

  • C#验证码识别类完整实例

    本文实例讲述了C#验证码识别类.分享给大家供大家参考.具体实现方法如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; namespace 验证码处理 { class VerifyCode {

  • C++动态分配和撤销内存以及结构体类型作为函数参数

    C++动态分配内存(new)和撤销内存(delete) 在软件开发过程中,常常需要动态地分配和撤销内存空间,例如对动态链表中结点的插入与删除.在C语言中是利用库函数malloc和free来分配和撤销内存空间的.C++提供了较简便而功能较强的运算符new和delete来取代malloc和free函数. 注意: new和delete是运算符,不是函数,因此执行效率高. 虽然为了与C语言兼容,C++仍保留malloc和free函数,但建议用户不用malloc和free函数,而用new和delete运算

  • C#编程自学之数据类型和变量一

    一.数据类型与变量的介绍 在程序运行的过程中计算机需要记录大量的状态 数据(这里我们统称数据).那这些数据都存放在哪呢?程序在运行过程中的数据一般都存放在内存.那么他们在内存中如何存放的一种描述就是数据类型.变量则就是数据类型的实体.那么我们来看一个例子: 假如现在需要设计一个程序计算整数 10 与 20 的和, 请看如下代码: using System; namespace MyProgram { class Program { static void Main(string[] args)

  • C#实现的XML操作类实例

    本文实例讲述了C#实现的XML操作类.分享给大家供大家参考.具体如下: 这里讲述了C#写的一个XML操作类,包括读取/插入/修改/删除. using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.W

  • C# 多态性的深入理解

    MSDN 上面的定义:通过继承,一个类可以有多种类型:可以用作它自己的类型,任何基类型,或者在实现接口时用作任何接口的类型.从两个方面来说明多态1.在运行时,方法参数和集合或者是数组等位置,派生类的对象都可以作为基类的对象处理,发生此情况时,该对象的声明类型不再与运行时类型相同.2.基类定义实现虚方法,派生类重写这些方法,在运行时,CLR会查找运行时类型,并且调用派生类重写的方法. 复制代码 代码如下: class Shape    {        public virtual void Dr

  • C#实现的简单链表类实例

    本文实例讲述了C#实现的简单链表类.分享给大家供大家参考.具体如下: 一.关于C#链表 C#链表可用类LinkedList来存放.本文中的类MyLinkedList只是实现了该类的最基本的功能.C#中没有指针,但因为C#中类在赋值时传递的是地址,因此仍然可以利用这点制作一个链表. 二.结点类Node和链表类MyLinkedList代码 /// <summary> /// 链表结点 /// </summary> class Node { //结点数据,前后结点 public obje

  • C#编程自学之数据类型和变量二

    我们继续自学C#编程教程,在上一课中介绍了C#的基本数据类型以及变量,今天这一节课我们来介绍值类型与引用类型! 一.什么是值类型与引用类型? C#与大多数面向对象语言数据类型一样,分为值类型与引用类型两种?如何区分这两种类型?如图: 根据类型结构图我们得出: 1.值类型包括 内置数据类型如(int double float) 用户自定义值类型(struct 结构体) 枚举(emun) 2.引用类型包括 接口类型 类类型等等. 知道了那些类型属于值类型与那些类型属于引用类型之后,我们来分析一下值类

  • C#实现实体类与字符串互相转换的方法

    本文实例讲述了C#实现实体类与字符串互相转换的方法.分享给大家供大家参考.具体实现方法如下: using System; using System.Collections.Generic; using System.Text; namespace PackDLL.Data.ConvertData { /// <summary> /// 实体类.字符串互相转换 /// </summary> public class PackReflectionEntity<T> { //

  • C#实现将类的内容写成JSON格式字符串的方法

    本文实例讲述了C#实现将类的内容写成JSON格式字符串的方法.分享给大家供大家参考.具体如下: 本例中建立了Person类,赋值后将类中内容写入到字符串中 运行本代码需要添加引用动态库Newtonsoft.Json 程序代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; //需要引用 Newtonsoft.Js

  • 详解Oracle数据库各类控制语句的使用

    Oracle数据库各类控制语句的使用是本文我们主要要介绍的内容,包括一些逻辑控制语句.Case when的使用.While的使用以及For的使用等等,接下来我们就开始一一介绍这部分内容,希望能够对您有所帮助. Oracle 中逻辑控制语句  If elsif else end if set serverout on; declare per_dep_count number; begin select count(*) into per_dep_count from emp; if per_de

  • C#通过Semaphore类控制线程队列的方法

    本文实例讲述了C#通过Semaphore类控制线程队列的方法.分享给大家供大家参考.具体实现方法如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Diagnostics; using System.Threading; using System.ComponentModel; using System.Col

随机推荐