docs.scala-lang.org/tour/generic-classes.html
위 사이트를 참고 하였음(제네릭의 기본적인 개념은 JAVA(witcheryoon.tistory.com/158?category=911325)를 참조하라.
Defining a generic class
제네릭 클래스는 Square bracket [ ] 안에 있는 파라미터로 정의한 타입을 가진다.
위의 예제에서 Stack에 A는 어떠한 타입으로도 정의할 수있다.
(참고 : x :: elements는 x를 elements(List)에 append 하는 방법)
Usage
아래처럼 Int로 정의하면 Int로 쓸수 있고 Fruie이라는 클래스를 정의해서 사용하면 그것도 허용된다.
Varaince
Variance은 복합적인 타입간의 관계를 설정하는 방법이다. 스칼라는 이를 사용하기 쉽게 에노테이션을 제공한다.
(
Variance is the correlation of subtyping relationships of complex types and the subtyping relationships of their component types. Scala supports variance annotations of type parameters of generic classes, to allow them to be covariant, contravariant, or invariant if no annotations are used. The use of variance in the type system allows us to make intuitive connections between complex types, whereas the lack of variance can restrict the reuse of a class abstraction.
)
Covariant(공변), Contravariant(반공변), Invariant(무공변)은 다음과 같다.
Covariance
타입 정의를 할때 + 를 붙여주면 공변관계를 만들 수 있다.
예를들어... 원래는, B가 A의 하위 타입이면, List[B]는 List[A]의 하위 타입이 아니다. 하지만 Covariance를 쓰면 이를 하위타입으로 만들수 있다는 것이다.
스칼라는 스탠다드 라이브러리에 sealed abstract class List[+A] 를 가지고 있으며 A를 공변시킬 수 있도록 되어있다.
(
Both Cat and Dog are subtypes of Animal. The Scala standard library has a generic immutable sealed abstract class List[+A] class, where the type parameter A is covariant. This means that a List[Cat] is a List[Animal] and a List[Dog] is also a List[Animal]. Intuitively, it makes sense that a list of cats and a list of dogs are each lists of animals, and you should be able to use either of them for in place of List[Animal]
In the following example, the method printAnimalNames will accept a list of animals as an argument and print their names each on a new line. If List[A] were not covariant, the last two method calls would not compile, which would severely limit the usefulness of the printAnimalNames method.
)
참고( kotlin으로 바꿔본 코드 )
Contravariance
반공변성은 - 애노테이션을 사용하여 표현한다. 공변성과 반대되는 개념.
예를들어 class Writer[-A]라고 표현했다고 가정하자.
이때, A가 B의 하위타입일 경우, 역으로, Write[B]가 Write[A]의 하위타입이 된다는 것
(
A type parameter A of a generic class can be made contravariant by using the annotation -A. This creates a subtyping relationship between the class and its type parameter that is similar, but opposite to what we get with covariance. That is, for some class Writer[-A], making A contravariant implies that for two types A and B where A is a subtype of B, Writer[B] is a subtype of Writer[A].
)
아래 예제를 생각해보자
추상화된 프린터는 반공변적이여야한다.
Printer[Animal]를 상속받은 AnimalPrinter는 Animal 이름을 print로 출력한다.
CatPrinter도 마찬가지로 Cat의 이름을 출력한다.
그런데 Animal의 하위타입으로 Cat이 정의 되어있다.
Printer[Animal]은 Cat을 어떻게 출력하는지 안다.
하지만 Printer[Cat]은 Animal을 어떻게 출력하는지 모른다.
즉, Animal의 하위타입인 Cat
(
If a Printer[Cat] knows how to print any Cat to the console, and a Printer[Animal] knows how to print any Animal to the console, it makes sense that a Printer[Animal] would also know how to print any Cat. The inverse relationship does not apply, because a Printer[Cat] does not know how to print any Animal to the console. Therefore, we should be able to use a Printer[Animal] in place of Printer[Cat], if we wish, and making Printer[A] contravariant allows us to do exactly that.
)
Invariance
'Programming Theory > Generics' 카테고리의 다른 글
Generics - java(2) (0) | 2020.12.04 |
---|---|
Generics -java(1) (0) | 2020.12.02 |