Полезно понять, почему это незаконно. Функция, которую вы хотите, это формальный тип параметра covariance, и очень немногие языки предлагают его. (Эйфель, я думаю, это как особенность.) Он не часто встречается на языках, потому что он небезопасен! Позвольте мне проиллюстрировать пример:
class Animal {}
class Lion : Animal { public void Roar() { } }
class Giraffe : Animal { }
interface IFoo { void M(Animal a); }
class C : IFoo
{
public void M(Lion lion) { lion.Roar(); }
}
class P
{
public static void Main()
{
IFoo foo = new C();
foo.M(new Giraffe());
}
}
И мы просто сделали рев жирафа.
Если вы посмотрите на все эти преобразования типов, единственное, что можно разумно сделать незаконным, соответствует C.M(Giraffe)
- IFoo.M(Animal)
.
Теперь, формальный параметр типа контрвариантность является типизированного но это не является законным в C# за исключением некоторых очень ограниченных обстоятельствах. Если C# поддерживает его, что это не так, то вы могли бы безопасно сделать что-то вроде этого:
interface IBar { void M(Giraffe g); }
class D : IBar
{
public void M(Animal animal) { ... }
}
class P
{
public static void Main()
{
IBar bar = new D();
bar.M(new Giraffe());
}
}
посмотреть, что там произошло? IFoo.M говорит: «Я могу взять жирафа», а C.M говорит: «Я могу принять любого жирафа, потому что на самом деле я могу принять любого животного». Это было бы типичным, если бы C# поддерживал его, но он поддерживает его только двумя способами:
- Контравариантный общий делегат и преобразования интерфейса.
- Контравариантные преобразования групп методов в типы делегатов.
Примером первого является то, что выражение типа IComparable<Animal>
может быть присвоено переменной типа IComparable<Giraffe>
той же самой логикой: метод, который сравнивает два животных могут быть использованы, где это метод, который сравнивает два жирафа требуется , Это был добавлен в C# 4.
Примером второго является:
delegate void MyFunction(Giraffe g);
...
D d = new D();
MyFunction myfunc = d.M;
Опять же, нам нужна функция, которая принимает жирафа, и мы поставляем один, который принимает любое животное. Эта функция была добавлена в C# 2.
Вы должны сделать сам интерфейс универсальным и дать классу реализации желаемый тип. – Rik
Как насчет того, чтобы не иметь параметр в методе печати и сделать каждый подкласс инъекцией реализации IClass в contructor или sertter. –
Метод toString наследуется от Object, поэтому почему вам действительно нужно иметь 'print (элемент MyClass)', а не только 'print (Object item)'? Вы скрываете этот метод? – Thomas