Как совместное и противоречивое использование при проектировании бизнес-приложений?

Я знаю об использовании co- и contravariance в стандартной библиотеке (например, коллекции и trait Function). Интересно, как co- и contravariance используются при разработке бизнес-приложений реального мира.

Ответ 1

Классический пример - это функции, использующие интерфейс Scala для функции с одним аргументом:

trait Function1[-T1, +R]

Что является контравариантным (-) для аргумента и ковариантным (+) для возвращаемого типа.

Почему?

Представьте, что у вас есть эти классы:

class Timelord { ... }
class Doctor extends Timelord { ... }

class Enemy { ... }
class Dalek extends Enemy { ... }

Если у вас есть метод, который принимает в качестве параметра функцию Doctor => Enemy; то в порядке, чтобы предоставить экземпляр TimeLord => Enemy. Он по-прежнему будет принимать экземпляры Doctor.

So TimeLord => Enemy является подклассом Doctor => Enemy, потому что TimeLord является суперклассом Doctor, он контравариантным в этом параметре.

Аналогично, функция, возвращающая Dalek, действительна, когда вам нужна функция, возвращающая некоторый Enemy, потому что a Dalek is-an Enemy

Итак, Doctor => Dalek является подклассом Doctor => Enemy, потому что Dalek является подклассом Enemy, он ковариантным в этом параметре.

Ответ 2

В любом месте, где вы хотите использовать параметрический полиморфизм (generics) и наследование, вы, вероятно, в конечном итоге захотите либо отклонение сайта объявления (+/-), использовать отклонение сайта (подстановочные знаки), или, более вероятно, оба.

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

Если вы посмотрите на практически любую библиотеку или фреймворк, вы часто пользуетесь аннотациями дисперсии. Если вы правильно отлаживаете свое приложение "реального мира", вы, вероятно, будете писать множество библиотек для его поддержки, а небольшое ядро ​​критически важной бизнес-логики прекрасно отделено от всей инфраструктуры поддержки. Все, что поддерживает инфраструктуру, вероятно, также часто используют аннотации изменений.