Kniga-Online.club
» » » » Герберт Шилдт - C# 4.0: полное руководство

Герберт Шилдт - C# 4.0: полное руководство

Читать бесплатно Герберт Шилдт - C# 4.0: полное руководство. Жанр: Программирование издательство -, год 2004. Так же читаем полные версии (весь текст) онлайн без регистрации и SMS на сайте kniga-online.club или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.
Перейти на страницу:

А теперь рассмотрим следующую простую реализацию иерархии классов.

// Создать простую иерархию классов,

class Alpha {

  string name;

  public Alpha(string n) { name = n; }

  public string GetName() { return name; }

// ...

}

class Beta : Alpha {

  public Beta(string n) : base (n) { }

// ...

}

Как видите, класс Beta является производным от класса Alpha.

С учетом всего изложенного выше, следующая последовательность операций будет считаться вполне допустимой.

// Создать ссылку из интерфейса IMyCoVarGenIF на объект типа MyClass<Alpha>.

// Это вполне допустимо как при наличии ковариантности, так и без нее.

IMyCoVarGenIF<Alpha> AlphaRef =

         new MyClass<Alpha>(new Alpha("Alpha #1"));

Console.WriteLine("Имя объекта, на который ссылается переменная AlphaRef: " +

        AlphaRef.GetObject().GetName());

//А теперь создать объект MyClass<Beta> и присвоить его переменной AlphaRef.

// *** Эта строка кода вполне допустима благодаря ковариантности. ***

AlphaRef = new MyClass<Beta>(new Beta("Beta #1"));

Console.WriteLine("Имя объекта, на который теперь ссылается " +

       "переменная AlphaRef: " + AlphaRef.GetObject().GetName());

Прежде всего, переменной AlphaRef типа IMyCoVarGenIF<Alpha> в этом фрагменте кода присваивается ссылка на объект типа MyClass<Alpha>. Это вполне допустимая операция, поскольку в классе MyClass реализуется интерфейс IMyCoVarGenIF, причем и в том, и в другом в качестве аргумента типа указывается Alpha. Далее имя объекта выводится на экран при вызове метода GetName() для объекта, возвращаемого методом GetObject(). И эта операция вполне допустима, поскольку Alpha — это и тип, возвращаемый методом GetName(), и обобщенный тип Т. После этого переменной AlphaRef присваивается ссылка на экземпляр объекта типа MyClass<Beta>, что также допустимо, потому что класс Beta является производным от класса Alpha, а обобщенный тип Т — ковариантным в интерфейсе IMyCoVarGenIF. Если бы любое из этих условий не выполнялось, данная операция оказалась бы недопустимой.

Ради большей наглядности примера вся рассмотренная выше последовательность операций собрана ниже в единую программу.

// Продемонстрировать ковариантность в обобщенном интерфейсе,

using System;

// Этот обобщенный интерфейс поддерживает ковариантность.

public interface IMyCoVarGenIF<out Т> {

  Т GetObject();

}

// Реализовать интерфейс IMyCoVarGenIF.

class MyClass<T> : IMyCoVarGenIF<T> {

  T obj;

  public MyClass(T v) { obj = v; }

  public T GetObject() { return obj; }

}

// Создать простую иерархию классов,

class Alpha {

  string name;

  public Alpha(string n) { name = n; }

  public string GetName() { return name; }

  // ...

}

class Beta : Alpha {

  public Beta(string n) : base(n) { }

  // ...

}

class VarianceDemo {

  static void Main() {

    // Создать ссылку из интерфейса IMyCoVarGenIF на объект типа MyClass<Alpha>.

    // Это вполне допустимо как при наличии ковариантности, так и без нее.

    IMyCoVarGenIF<Alpha> AlphaRef =

           new MyClass<Alpha>(new Alpha("Alpha #1"));

    Console.WriteLine("Имя объекта, на который ссылается переменная " +

          "AlphaRef: " + AlphaRef.GetObject().GetName());

    //А теперь создать объект MyClass<Beta> и присвоить его // переменной AlphaRef.

    // *** Эта строка кода вполне допустима благодаря ковариантности. ***

    AlphaRef = new MyClass<Beta>(new Beta("Beta #1"));

    Console.WriteLine("Имя объекта, на который теперь ссылается переменная "

         + "AlphaRef: " + AlphaRef.GetObject().GetName());

  }

}

Результат выполнения этой программы выглядит следующим образом.

Имя объекта, на который ссылается переменная AlphaRef: Alpha #1

Имя объекта, на который теперь ссылается переменная AlphaRef: Beta #1

Следует особо подчеркнуть, что переменной AlphaRef можно присвоить ссылку на объект типа MyClass<Beta> благодаря только тому, что обобщенный тип Т указан как ковариантный в интерфейсе IMyCoVarGenIF. Для того чтобы убедиться в этом, удалите ключевое слово out из объявления параметра обобщенного типа Т в интерфейсе IMyCoVarGenIF и попытайтесь скомпилировать данную программу еще раз. Компиляция завершится неудачно, поскольку строгая проверка на соответствие типов не разрешит теперь подобное присваивание.

Один обобщенный интерфейс может вполне наследовать от другого. Иными словами, обобщенный интерфейс с параметром ковариантного типа можно расширить, как показано ниже.

public interface IMyCoVarGenIF2<out Т> : IMyCoVarGenIF<T> {

// ...

}

Обратите внимание на то, что ключевое слово out указано только в объявлении расширенного интерфейса. Указывать его в объявлении базового интерфейса не только не нужно, но и не допустимо. И последнее замечание: обобщенный тип Т допускается не указывать как ковариантный в объявлении интерфейса IMyCoVarGenIF2. Но при этом исключается ковариантность, которую может обеспечить расширенный интерфейс IMyCoVarGetlF. Разумеется, возможность сделать интерфейс IMyCoVarGenIF2 инвариантным может потребоваться в некоторых случаях его применения.

На применение ковариантности накладываются некоторые ограничения. Ковариантность параметра типа может распространяться только на тип, возвращаемый методом. Следовательно, ключевое слово out нельзя применять в параметре типа, служащем для объявления параметра метода. Ковариантность оказывается пригодной только для ссылочных типов. Ковариантный тип нельзя использовать в качестве ограничения в интерфейсном методе. Так, следующий интерфейс считается недопустимым.

public interface IMyCoVarGenIF2<out Т> {

  void M<V>() where V:T; // Ошибка, ковариантный тип T нельзя

  // использовать как ограничение

}

Применение контравариантности в обобщенном интерфейсе

Применительно к обобщенному интерфейсу контравариантность служит средством, разрешающим методу использовать аргумент, тип которого относится к базовому классу, указанному в соответствующем параметре типа. В прошлом тип аргумента метода должен был в точности соответствовать параметру типа в силу строгой проверки обобщений на соответствие типов. Контравариантность смягчает это строгое правило таким образом, чтобы обеспечить типовую безопасность. Параметр контравариантного типа объявляется с помощью ключевого слова in, которое предваряет имя этого параметра.

Для того чтобы стали понятнее последствия применения ковариантности, вновь обратимся к конкретному примеру. Ниже приведен обобщенный интерфейс IMyContraVarGenIF контравариантного типа. В нем указывается контравариантный параметр обобщенного типа Т, который используется в объявлении метода Show().

// Это обобщенный интерфейс, поддерживающий контравариантность.

public interface IMyContraVarGenIF<in Т> {

  void Show(T obj);

}

Как видите, обобщенный тип Т указывается в данном интерфейсе как контравариантный с помощью ключевого слова in, предшествующего имени его параметра. Обратите также внимание на то, что Т является параметром типа для аргумента obj в методе Show().

Далее интерфейс IMyContraVarGenIF реализуется в классе MyClass, как показано ниже.

// Реализовать интерфейс IMyContraVarGenIF.

class MyClass<T> IMyContraVarGenIF<T> {

  public void Show(T x) {

    Console.WriteLine(x);

Перейти на страницу:

Герберт Шилдт читать все книги автора по порядку

Герберт Шилдт - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки kniga-online.club.


C# 4.0: полное руководство отзывы

Отзывы читателей о книге C# 4.0: полное руководство, автор: Герберт Шилдт. Читайте комментарии и мнения людей о произведении.


Уважаемые читатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.

  • 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
  • 2. Просьба отказаться от оскорблений, угроз и запугиваний.
  • 3. Просьба отказаться от нецензурной лексики.
  • 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.

Надеемся на Ваше понимание и благоразумие. С уважением, администратор kniga-online.


Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*