Хорошо, шаг за шагом.
iPoppable<Lion> lions = new Group<Lion>();
работы, потому что Group
реализует iPoppable
и универсальный параметр T
то же самое.
iPoppable<Animal> animals = lions;
работы, потому что оба они являются iPoppable
и Lion
происходит от Animal
. Более формально это пример covariance.
Объект, созданный с использованием аргумента более производного типа, присваивается объекту, созданному с использованием аргумента с менее производным типом. Совместимость присвоений сохраняется.
Microsoft Docs.
Group<Lion> lions2 = lions;
Не работает, потому что вы назначаете тип интерфейса типу класса. iPoppable
просто говорит, что lions
имеет Lion Pop();
метод, не более! Говоря Group<Lion> lions2 = lions;
, вы утверждаете, что lions2
- полнофункциональный объект Group
, который будет иметь все методы и свойства Group
класс. Который не обязательно true, и поэтому компилятор жалуется.
Вы можете помочь компилятору говоря
Group<Lion> lions2 = (Group<Lion>)lions;
потому что вы знаете, за то, что особенно lions
, хотя тип iPoppable
фактически Group
.
Чтобы проиллюстрировать, что компилятор боится, см. Следующий фрагмент.
interface iPoppable<out T>
{
T Pop();
}
interface iPushable<in T>
{
void Push(T ag_t);
}
class Program
{
static void Main()
{
// Here, we know the truth, so we cast
iPoppable<bool> group = new Group<bool>();
Group<bool> group2 = (Group<bool>)group; // Possible
// What about here? We also convert iPoppable to Group...
iPoppable<bool> notGroup = new NotGroup<bool>();
Group<bool> notGroup2 = (Group<bool>)notGroup; // Bad... Compiler was right...
notGroup2.HelloGroup = true; // HA! Runtime exception.
// That's what compiler was worrying about.
// System.InvalidCastException: Unable to cast object of
// type 'NotGroup`1[System.Boolean]' to type 'Group`1[System.Boolean]
}
}
class Group<T> : iPoppable<T>, iPushable<T>
{
public void Push(T ag_t) { }
public T Pop() { return default(T); }
public bool HelloGroup { get; set; }
}
class NotGroup<T> : iPoppable<T>, iPushable<T>
{
public void Push(T ag_t) { }
public T Pop() { return default(T); }
public bool HelloNotGroup { get; set; }
}
Для начала ваша подпись в вашей группе 'Group' неверна. Pop должен возвращать объект типа 'T', а не void. Также вам нужно изучить работу с ковариацией * и * контравариантность. – lintmouse
Спасибо. просто исправлено. И да. Я просто читал о них обоих. –