从父类调用重写虚方法

时间:2011-08-02 22:03:30

标签: c# oop inheritance

假设您正在编写原始的C#Object类,并且您需要以下功能:

  1. object1 == object2将比较引用,除非重写此运算符
  2. object1 != object2将始终返回对象的ACTUAL object1 == object2
  3. 的反转

    因此,例如,如果我有一个Bunny类(派生自Object)使用ear length作为其equals方法,那么notequals方法(继承自Object)应该如果兔子的耳长不同,则返回true。

    我看到的问题是,如果我写了Object类,那就是:

    public partial class Object {
        public virtual bool Equals(Object o2) {
           return (this === o2);
        }
    
        public bool NotEquals(Object o2) {
           return !this.Equals(o2);
        }
    }
    

    那么似乎该定义会将NotEquals绑定到Object的Equals,而不是实际派生类的equals。

    有什么方法可以在不以任何方式修改C#本身的情况下工作?我并不在乎C#中的可能性,但我关心是否有一些OOP原则告诉我我不应该期待这种事情能够发挥作用。

    另外,我不确定这是否是这个问题的基础,但是想法是NotEquals也是虚拟的,以便它也可以被希望它们o1 != o2的派生类覆盖。与!(o1 == o2)不同。这个问题的灵感来自this recent discussion

4 个答案:

答案 0 :(得分:6)

您提供的代码调用派生的Equals方法。 Equals是虚拟的,这意味着当它被调用时,将使用“派生最多”的实现。

答案 1 :(得分:3)

NotEquals不会绑定到Object类的equal方法,它将使用派生最多的方法。你可以很容易地测试这个。而且,将notEquals设置为虚拟也很容易,因此您也可以使用自定义逻辑覆盖它。

使用这些类(忽略可怕的命名约定):

class parent
{
    public virtual bool equals(parent p)
    {
        Console.WriteLine("parent equals");
        return false;
    }

    public virtual bool notEquals(parent p)
    {
        return !this.equals(p);
    }
}

class child : parent
{
    public override bool equals(parent p)
    {
        Console.WriteLine("child equals");
        return true;
    }
}

然后运行:

parent p = new parent();
p.notEquals(null);

child c = new child();
c.notEquals(null);

此输出结果:

parent equals
child equals

答案 2 :(得分:3)

我可能误解了这个问题,但是在您的示例中NotEquals中声明的Object方法将使用在派生类上定义的Equals方法(如果使用覆盖声明它派生类中的修饰符),而不是Object本身。

举一个演示此行为的简单示例:

void Main()
{
    BaseObject do1 = new DerivedObject();
    BaseObject do2 = new DerivedObject();
    do1.NotEquals(do2);
}


public class DerivedObject : BaseObject
{
    public override bool Equals(BaseObject o2)
    {
        Console.WriteLine("OtherObject.Equals called.");
        return (this == o2);
    }
}

public partial class BaseObject {
    public virtual bool Equals(BaseObject o2) {
       return (this == o2);
    }

    public bool NotEquals(BaseObject  o2) {
       return !this.Equals(o2);
    }
}

如果执行该示例,您将看到执行Console.WriteLine语句(在DerivedObject上删除override修饰符,然后不执行Console.WriteLine)。

您还可以查看documentation,其中指出:“如果没有派生类覆盖该成员,则调用最派生类中的重写成员,该成员可能是原始成员。”。

答案 3 :(得分:1)

目前还不完全清楚你要问的是什么,因为你无法改变Object的定义,所以这个练习有些没有实际意义,但假装你可以并且实际上正在改变Object class,this.Equals 实际上是指派生类的实现,因为Equals是虚拟的。

特别是我不确定你的句子中的“this”是什么意思:

“在没有以任何方式修改C#本身的情况下,这个能否正常工作?”