Ответ 1
Код, который вы предоставили, вызовет производный метод Equals
. Equals
является виртуальным, и это означает, что при его вызове будет использоваться "наиболее производная" реализация.
Предположим, вы пишете исходный класс С# Object
, и вам нужны следующие функции:
object1 == object2
будет сравнивать ссылки, если этот оператор не переопределен.object1 != object2
всегда будет возвращать обратный объекту ACTUAL 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, а не к фактическому производному классу.
Есть ли способ, которым это может работать без изменения самого С#? Мне все равно, что это возможно на С#, но мне все равно, есть ли какой-то принцип ООП, который говорит мне, что я не должен ожидать, что это будет работать.
Кроме того, я не уверен, является ли это основополагающим для этого вопроса, но идея заключается в том, чтобы NotEquals был виртуальным, так что он тоже может быть переопределен производными классами, которые хотят, чтобы их o1 != o2
отличались друг от друга от !(o1 == o2)
. Этот вопрос вдохновлен этим недавним обсуждением.
Код, который вы предоставили, вызовет производный метод Equals
. Equals
является виртуальным, и это означает, что при его вызове будет использоваться "наиболее производная" реализация.
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
Возможно, я не понимаю вопроса, но метод 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, а затем Console.WriteLine не будет выполнен).
Вы также можете просмотреть документацию, в которой говорится: "Вызывается переопределяющий член в самом производном классе, который может быть исходным членом, если никакой производный класс не переопределил член.".
Это не совсем понятно, что вы пытаетесь спросить, потому что вы не можете изменить определение Object
поэтому упражнение несколько спорно, но делать вид, что вы можете и на самом деле изменения Object
, <класс T22 > на самом деле ссылаются на реализацию производного класса, поскольку Equals
является виртуальным.
В частности, я не уверен, что вы подразумеваете под "this" в своем предложении:
"Есть ли способ, которым этот может работать без изменения самого С#?"