Как вы справляетесь с переопределением функций с различными типами результатов? - PullRequest
4 голосов
/ 26 мая 2011

Наиболее очевидный случай проблемы - функция Clone (просто ПРИМЕР ребята). Допустим, у вас есть BaseClass и DerivedClass - если я чего-то не пропущу, в обеих функциях (клон для каждого класса) вы создаете BaseClass и DerivedClass соответственно, но фактически возвращаете объект. Это проблема, если вы хотите работать с «настоящим» классом.

Пока я вижу только два обходных решения этой проблемы:

1. каждый раз приводите результат функции к соответствующему классу

var real_stuff = (RealStuff)x.Clone(); // I want real stuff

2. предоставляют вторую функцию, поэтому у вас будут Clone (если вы работаете на уровне базового класса) и CloneThis (результат будет меняться от класса к классу, если вы хотите работать на данном уровне класса) )

   public override object Clone()
    {
       return CloneThis();
    }
    public RealStuff CloneThis()
    {
       return new RealStuff(this);
    }

Первый уродлив, второй утомителен.

ВОПРОС : как вы решаете эту проблему?

Другое дело - пожалуйста, прокомментируйте это, если хотите, - почему при переопределении проверки подписи функции так строги? Кроме того «потому что он был спроектирован таким образом» или любимого Эрика Липперта «потому что каждая функция требует ...» ;-) Я не вижу никаких технических (и логических и т. Д.) Проблем с возможностью переопределения функции с измененным типом результата IF результат переопределенной функции выводится из исходного типа результата функции.

Пример:

  class ClassA
  {
    public virtual ClassA GetIt() ...
  }

  class ClassB : ClassA
  {
    public override ClassB GetIt() ...
  }

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

Чтобы вы могли написать:

  ClassA class_a_b = new ClassB();
  ClassB class_b_b = new ClassB();

  ClassA result1 = class_b_b.GetIt();
  ClassA result2 = class_a_b.GetIt();
  ClassB result3 = class_b_b.GetIt();
  // incorrect, derived GetIt would be called OK, 
  // but the signature is taken from ClassA
  ClassB result4 = class_a_b.GetIt(); 

Я тоже не думаю, что с такими возможностями кто-нибудь будет удивлен поведением, ИМХО, оно соответствует.

Пожалуйста, сохраняйте свои ответы по теме: «Вы не должны использовать ICloneable» - это НЕ по теме. Спасибо.

1 Ответ

3 голосов
/ 26 мая 2011

Проверьте эти два вопроса:

В основном, способ справиться с этим - определить универсальный интерфейс с соответствующим типом возвращаемого значения, например

interface ICloneable<T> {
    T Clone();
}

Это, однако, не позволяет использовать интерфейс в качестве базового типа, поскольку ICloneable и ICloneable - это две разные вещи.

Было бы "технически возможно" иметь функции, отличающиеся только типом возвращаемого значения, и в действительности CLR допускает это, а C # - нет, возможно, потому что было бы невозможно всегда угадать правильную перегрузку для вызова. (На самом деле в C # вы можете сделать это с неявными операторами приведения: они компилируются в функции с именем op_Implicit и с другим типом возврата).

...