C#多态性

2019-10-16  本文已影响0人  86a262e62b0b

参考文档:
https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/polymorphism

一. 概念

多态性:指多种形态,具有两个截然不同的方面:

二. 基本使用

当派生类从基类继承时,它会获得基类的所有方法、字段、属性和事件。
派生类可以选择以下处理:

1. 重写基类中的虚拟成员,或不重写

注意:

示例:

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; }
    }
}

//当派生类重写某个虚拟成员时,即使该派生类的实例被当作基类的实例访问,也会调用该成员。
DerivedClass B = new DerivedClass();
B.DoWork();  // Calls the new method.

BaseClass A = (BaseClass)B;
A.DoWork();  // Also calls the new method.

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; }
    }
}

//通过将派生类的实例强制转换为基类的实例,仍然可以从客户端代码访问隐藏的基类成员。
DerivedClass B = new DerivedClass();
B.DoWork();  // Calls the new method.

BaseClass A = (BaseClass)B;
A.DoWork();  // Calls the old method.

3. 阻止派生类重写虚拟成员

public class A
{
    public virtual void DoWork() { }
}
public class B : A
{
    public override void DoWork() { }
}
public class C : B
{
    public sealed override void DoWork() { }
}

在上一示例中,方法 DoWork 对从 C 派生的任何类都不再是虚方法。它对 C 的实例仍是虚拟的,即使它们转换为类型 B 或类型 A。

public class D : C
{
    public new void DoWork() { }
}
  1. 在此情况下,如果在 D 中使用类型为 D 的变量调用 DoWork,被调用的将是新的 DoWork。
  2. 如果使用类型为 C、B 或 A 的变量访问 D 的实例,对 DoWork 的调用将遵循虚拟继承的规则,即把这些调用传送到类 C 的 DoWork 实现。

三. 方法的选择

public class Derived : Base
{
    public override void DoWork(int param) { }
    public void DoWork(double param) { }
}

int val = 5;
Derived d = new Derived();
d.DoWork(val);  // Calls DoWork(double).

=>

由于变量 val 可以隐式转换为 double 类型,因此 C# 编译器将调用 DoWork(double),而不是 DoWork(int)。

有两种方法可以避免此情况:

  1. 首先,避免将新方法声明为与虚方法相同的名称。
  2. 其次,可以通过将 Derived 的实例强制转换为 Base 来使 C# 编译器搜索基类方法列表,从而使其调用虚方法。 又由于是虚方法,因此将调用 Derived 上的 DoWork(int) 的实现。 例如:
((Base)d).DoWork(val);  // Calls DoWork(int) on Derived.

四.

更多案例请参考文档:
https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/knowing-when-to-use-override-and-new-keywords

五. How to: Override the ToString Method

C# 中的每个类或结构都可隐式继承 Object 类。 因此,C# 中的每个对象都会获取 ToString 方法,

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    public override string ToString()
    {
        return "Person: " + Name + " " + Age;
    }
}
上一篇 下一篇

猜你喜欢

热点阅读