Вызов переопределенных виртуальных методов из родительского класса - PullRequest
3 голосов
/ 03 августа 2011

Скажем, вы писали оригинальный класс C # Object и хотели получить следующую функциональность:

  1. object1 == object2 будет сравнивать ссылки, если этот оператор не переопределен
  2. object1 != object2 всегда возвращает значение, обратное действительному для объекта object1 == object2

Так, например, если у меня есть класс Bunny (производный от Object), который использует длину уха в качестве метода 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, а не с фактическими производными классами.

Есть ли способ, которым это может работать без какого-либо изменения самого C #? Мне все равно, что это возможно в C #, но меня волнует, есть ли какой-то принцип ООП, который говорит мне, что я не должен ожидать, что подобные вещи будут работать.

Кроме того, я не уверен, является ли это основополагающим для вопроса, но идея заключается в том, чтобы NotEquals также был виртуальным, чтобы его можно было переопределить производными классами, которые хотят, чтобы их o1 != o2 были другими от !(o1 == o2). Этот вопрос вдохновлен этим недавним обсуждением .

Ответы [ 4 ]

6 голосов
/ 03 августа 2011

Код, который вы указали , будет вызывать производный метод Equals.Equals является виртуальным, и это означает, что при его вызове будет использоваться «наиболее производная» реализация.

3 голосов
/ 03 августа 2011

Возможно, я неправильно понял вопрос, но метод NotEquals, объявленный в Object в вашем примере, будет использовать метод Equals, определенный в производном классе (если он объявлен с модификатором override в производном классе), не на 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 (уберите модификатор override в DerivedObjectи тогда Console.WriteLine не будет выполняться).

Вы также можете просмотреть документацию , в которой говорится: «Вызывается переопределяющий член в наиболее производном классе, который может быть исходным членом, если ни один производный класс не переопределил член.».

3 голосов
/ 03 августа 2011

NotEquals не будет связываться с методом равных класса Object, он будет использовать самый производный метод. Вы могли бы легко проверить это. Также легко сделать виртуальный 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
1 голос
/ 03 августа 2011

Это не совсем понятно, что вы пытаетесь спросить, потому что вы не можете изменить определение Object поэтому упражнение несколько спорно, но делать вид, что вы можете и на самом деле изменения Object класс this.Equals будет фактически относиться к реализации производного класса, потому что Equals является виртуальным.

В частности, я не уверен, что вы подразумеваете под "этим" в предложении:

"Есть ли способ, которым этот может работать без какого-либо изменения самого C #?"

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...