scala/basic
F-Bound
wefree
2022. 11. 12. 20:54
아래 코드를 생각해 보자
trait Animal {
def breed: List[Animal]
}
class Dog extends Animal {
override def breed: List[Animal] = ???
}
Dog class 의 breed 의 리턴 타입을 List[Animal] 이 아닌 List[Dog] 로 강제하고 싶다.
이런 필요성이 있을 때, F-Bound 로 제한할 수 있다.
trait Animal[A <: Animal[A]] {
def breed: List[A]
}
class Dog extends Animal[Dog] {
override def breed: List[Dog] = ???
}
그런데 이는 아래처럼 개발자가 실수로 잘못 상속 받는 것을 막지는 못한다.
trait Animal[A <: Animal[A]] {
def breed: List[A]
}
class Dog extends Animal[Dog] {
override def breed: List[Dog] = ???
}
// Cat class 는 Animal[Cat] 을 상속받아야 하는데 Animal[Dog] 을 상속 받음
class Cat extends Animal[Dog] {
override def breed: List[Dog] = ???
}
이것까지 강제하고 싶다면, self 타입 으로 제한한다.
// self 타입으로 제한
trait Animal[A <: Animal[A]] { self: A =>
def breed: List[A]
}
class Dog extends Animal[Dog] {
override def breed: List[Dog] = ???
}
// 컴파일 에러 !!!
class Cat extends Animal[Dog] {
override def breed: List[Dog] = ???
}
지금까지 상속 + F-Bound + Self 타입으로 문제를 해결해 봤는데 복잡하다.
이럴 때 typeclass 를 이용해 해결하는 것은 매우 좋은 선택이 될 것 같다.