C#中普通函数重写

前言

在面向对象程序设计中,多态是非常重要的一个特性。多态能够实现同一基类的不同的类中重写的同名虚函数的不同功能表现。而在对这个基类的函数重写以后,原函数就不存在了,取而代之的是新的重写后的函数。比如,在C#的某个基类中有个虚函数:
public virtual void Say(){ print("base"); }
而在此类的派生类中,如果对Say()方法重写如下:
public void Say(){ print("Overrided Say()"); }
那么无论如何调用这个派生类的对象的Say()方法,返回的永远是 Overrided Say()

问题描述

在某个场合,比如Tom写了一个基类Person,Jack写了一个继承于Person的Student类。在实现的过程中,Jack需要为Student类添加一个函数GetName(),但是却发现在Person类中,已经有同名函数存在,而这个同名函数又不是虚函数,所以无法重写。这时候应该如何解决?

解决办法

在C#提供了一个有意思的特性,就是为一个普通函数提供重写方法。下面请看一个示例。
基类:Person

public class Person
{
	public string name { get; set; }
	public string GetName()
	{
		return name;
	}
}

派生类:Student

public class Student: Person
{
    public string _name;
	public new string GetName()
	{
		return "Student: " + _name;
	}
}

客户端使用码如下。

Person p = new Student() { name = "Tom" };
Console.WriteLine(p.GetName());
Console.WriteLine((p as Student).GetName());

输出结果:

Tom
Student: Tom

从这个输出来看,显然有2个GetName()方法,一个是与Person所有的,另一个是Student类所有的。这样以来,问题就解决了。不过在使用的时候,需要清楚不同的类所有的方法的使用。这种方法虽然能够解决问题,但是不推荐使用,因为这会让不同的函数在调用时让调用人员感到困扰,会有安全隐患。所以除非特殊情况,否则不推荐使用。还是以虚函数为主要实现方式。

总结

普通函数在C#中也可以进行重写,只是其重写方式与虚方法重写略有区别。比如,普通方法GetName()在基类和派生类中都有,而虚方法是共用一个。所以在调用时,以不同的级别(作为基类或派生类)调用时,就会有不同的结果。

另外,注意一点,如果不加new关键字,会有警告提示:“Student.GetName()”隐藏了继承的成员“Person.GetName()”。如果是有意隐藏,请使用关键字 new。经测试,目前的结论是,如果不加,系统会编译时按加了new关键字的情况来处理,即加不加都是一样的,不过不加系统会警告。可能加了以后比较清楚直观一点,一看就知道这是基类有的代码。

你可能感兴趣的:(C#语言详解)