Перегрузка оператора при наследовании

213
16 ноября 2021, 17:30

Можно как-нибудь наследовать перегрузку операторов? Сейчас я повторно дублирую код, например как в нижеприведенном коде.

Базовый класс

using System;
namespace Test
{
public class Base
{
    public double Num { get; set; }
    public Base()
    {
    }
    public Base(Base num)
    {
        Num = num.Num;
    }

    // Перегрузим арифметические операции в базовом классе
    public static Base operator +(Base x, Base y)
    {
        Base base = new Base();
        return new Base(base.Addition(x, y));
    }

    // Какая-то реализация (для перегрузки в базовом классе)
    public virtual Base Addition(Base x, Base y)
    {
        Base base = new Base();
        base.Num = ((x.Num + y.Num) + 10) / 2;
        return base;
    }
    public override string ToString()
    {
        return String.Format($"{Num} ");
    }
  }
}

Производный класс

namespace Test
{
public class RealNumber : Base
{
    public RealNumber()
    {
    }

    public RealNumber(RealNumber num)
    {
        Num = num.Num;
    }
    // Какая-то реализация (для перегрузки в производном классе)
    public RealNumber Addition(RealNumber x, RealNumber y)
    {
        RealNumber realNumber = new RealNumber();
        realNumber.Num = x.Num + y.Num;
        return realNumber;
    }

    public static RealNumber operator +(RealNumber x, RealNumber y)
    {
        RealNumber realNumber = new RealNumber();
        return new RealNumber(realNumber.Addition(x, y));
    }
  }
}
Answer 1

В простом явном виде нельзя.

Оператор определяется в статическом методе. Формально, по спецификации, они наследуются, но есть существенная разница в действующих механизмах наследования статических членов и членов экземпляра. По факту все наследование статических методов сводится к неограниченному доступу к данным методам через производные классы, но ни каких бонусов в виде адаптации сигнатуры под производный класс или возможности сделать метод виртуальным нет.

Есть обходные пути, для решения проблемы, один из них в соседнем ответе.

Answer 2

Наследование перегрузки операторов происходит само собой. Но все типы в сигнатуре останутся, как в предке. То есть при сложении двух RealNumber вы получите объект Base. Как с этим бороться описано здесь Наследование перегрузки операторов

А в следующем вопросе на эту тему (Генерация объектов наследников в коде предка и производительность) мне предложили отказаться от этой идеи. И в конечном итоге я выбрал этот вариант.

Answer 3

Используйте virtual методы. Я покажу на примере с IEquitable<T>

class Base : IEquitable<Base>
{
    public static readonly Base Default = new Base();
    public int BaseValue { get; }
    public Base(int value)
    {
        BaseValue = value;
    }
    public virtual bool Equals(Base? comparand) =>
        BaseValue == (comparand ?? Default).BaseValue;
    public static bool operator ==(Base? a, Base? b) =>
        a is null ? (b is null ? true : b.Equals(a)) : // у нас `null == Default` b `Default == null`
            a.Equals(b);
    public static bool operator !=(Base? a, Base? b) => !(a == b);
}
class Derived : Base, IEquitable<Derived>
{
    public new static readonly Derived Default = new Derived();
    public int DerivedValue { get; }
    public Derived(int baseValue, int value) : base(baseValue)
    {
        DerivedValue = value;
    }
    public virtual bool Equals(Derived? comparand) =>
        DerivedValue == (comparand ?? Default).DerivedValue &&
        base.Equals(comparand); // implicit case `Derived` -> `Base`
    public override bool Equals(Base? comparand) =>
        comparand is Derived derived ? Equals(derived) :
            base.Equals(comparand); // or `false`
    public static bool operator ==(Derived? a, Derived? b) =>
        a is null ? (b is null ? true : b.Equals(a)) : a.Equals(b);
    public static bool operator !=(Derived? a, Derived? b) => !(a == b);
}
READ ALSO
Как подключить кодировку UTF-8 в mysql?

Как подключить кодировку UTF-8 в mysql?

У меня есть опрос на сайте, оно с помощью sqlquery = select берет вопросы с базы данных, и показывает на сайте, но сейчас вместо букв стоит символ ?, как...

158
Не могу получить ссылку на скачку видео(Youtube)

Не могу получить ссылку на скачку видео(Youtube)

Не могу получить ссылку на скачку некоторых видео с ютуба https://wwwyoutube

84