b

SCALA UPPER/LOWER TYPE BOUND & VIEW BOUND 본문

language/scala

SCALA UPPER/LOWER TYPE BOUND & VIEW BOUND

dev.bistro 2017. 6. 28. 13:58

하나 이상의 타입인자가 있는 클래스는 ‘제네릭 클래스’이고  타입인자를 실제 타입으로 대체하면 일반 클래스이다.

1
2
3
4
class Pair[T,S](val first:T, val second:S) //제네릭 클래스
 
val p1 = new Pair(42, "String") //추론에 의해서 일반 클래스
val p2 = new Pair[Int, String](42, "String") //명시적 선언에 의해서 일반 클래스

 

함수,  메소드도 타입인자를 가질 수 있다.

1
2
3
4
5
def getMiddle[T](a: Array[T]) = a(a.length) / 2
 
ex)
getMiddle(Array("Mary", "had")) //추론의 의해서 getMiddle 호출
val f = getMiddle[String] _ //타입인자를 명시적으로 지정함

 

타입에 제한(bound)를 걸어야 할 필요가 있다. 다음의 예로 쉽게 이해 가능하다

1
2
3
4
5
6
7
8
9
10
11
class Pair[T](val first:T, val second:S) {
def smaller = if (first.compareTo(second) < 0 ) <<--여기
}
/* first가 compareTo를 가지고 있는지 확인 할 수 없기 때문에 오류가 발생한다.
이를 해결하기 위해서는 first가 'compareTo'를 항상 가지고 있으면 될 것이다. 아래처럼 */
 
class Pair[T <: Comparable[T]](val first: T, val second: T) {
def smaller = if (first.compareTo(second) < 0 )
}
/* 처럼 'T가 반드시 Comparable[T]의 sub-type'임을 지정하면 된다.
=> 그리고 'T의 상위 타입을 지정했거나, upper bound 지정,제약했다' 라고 표현 가능 */

 

그와 비슷하게 lower bound를 선언할 수도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Queue[+T] (private val leading: List[T], val trail: List[T] ) {
def enqueue[U >: T] (x: U) = new Queue[U](leading, x :: trail)
}
// U >: T 를 이용해 T 를 U 의 하위 바운드로 지정했으니 U가 T의 슈퍼클래스여야 한다.
 
ex1)
/* Fruit 클래스에 2개의 서브 클래스 Apple, Orange가 있다.
Queue[Apple]에 Oragne를 추가할 수 있고 결과는 Queue[Fruit]가 된다. */
 
ex2)
class Animal
class Bird extends Animal
class Chicken extends Bird
 
val flock = List(new Bird, new Bird)
flock: List[Bird] = List(Bird@7e1ec70e, Bird@169ea8d2)
 
new Chicken :: flock
res53: List[Bird] = List(Chicken@56fbda05, Bird@7e1ec70e, Bird@169ea8d2)
 
// 처럼 공통적인 각기 다른 타입을 하나로 분류할 수 있는 이점이 생긴다.

 

upper , lower bound와 같은 상하위가 아니라 implicit의 암묵적 변환에도 그대로 사용하고 싶을 경우에는 <% 를 사용한다.

1
2
3
4
5
6
7
8
9
10
11
class Pair[T <: Comparable[T] ](val first:T, val second:T)
val p = new Pair(4,2)
 
output> Error:(6, 9) inferred type arguments [Int] do not conform to class Pair's type parameter bounds [T <: Comparable[T]]
// 4, 2같은 Int는 Comparable를 구현하지 않기 때문이다 하지만 RichInt에는 있다.
 
class Pair[T <% Comparable[T] ](val first:T, val second:T)
/* 처럼 수정하면 된다. 이를 다시 풀어보면
a. T가 Comparable[T]로 암묵적 변환이 가능하다 라는 의미이다.
b. T를 Comparable[T]로 다룰수 있는 모든 T type을 사용 할 수 있다.
c. class Pair[T ](..)(implicit imp: T => Comparable[T]) 의 축약형이다.


'language > scala' 카테고리의 다른 글

SCALA TYPE ERASURE & TYPETAG  (0) 2017.06.30
Superseded by Akka HTTP  (0) 2017.05.01
FP 비엄격성  (1) 2015.05.18
scala package object  (0) 2014.11.05
scala의 lazy 비용  (0) 2014.10.21
Comments