Sealed Class를 사용하면 컴파일시에 상속받는 Child class가 무엇 있는지 알아 제한된다.
같은 패키지 안에 있는 child만으로 제한된다.
sealed class Color
object Red: Color()
object Green: Color()
object Blue: Color()
정의는 sealed class className으로 위와 같이 할 수 있다.
sealed 키워드를 붙이면 abstract 클래스가 된다.
val color: Color = Red
위와 같이 객체를 생성할 수 있다.
sealed class를 위와 같이 object class로 상속할 경우 singleton 패턴이 적용된다.
sealed class Color
class Red: Color()
class Green: Color()
class Blue: Color()
위와 같이 사용할 경우 equals, hashCode 를 오버라이드 해야한다.
class를 상속할 때 최상위 객체인 Any에는 override가 가능한 3가지 함수가 존재한다.
equals, hashcode, toString 함수이다.
예를들어 product를 아래와 같이 정의한다.
class Product(val categoryLabel: String, val name: String =""){
}
이후 아래와 같이 사용하면
val product = Product("패션, "롱 패딩")
println("$product")
우리가 원하는 categoryLabel: 패션, name: 롱 패딩 이런식으로 출력되지 않고
Product@어쩌구저쩌구 가 나올 것이다.
이는 우리이게 의미있는 정보가 아니다. 그러면 오버라이드를 해야한다
val product1 = Product("패션, "롱 패딩")
val product2 = Product("패션, "롱 패딩")
println(product1 == product2)
위의 결과는 false가 나온다.
우리는 true를 원할 것인데 false가 나온다.
같은 정보를 가지고 있으니 true라고 판단하고 싶다 false이니
override하면 된다.
val product1 = Product("패션, "롱 패딩")
val product2 = Product("패션, "롱 패딩")
val productSet = hashSetOf(product1)
println(productSet.contains(product2))
위의 결과는 false이다. 왜 false일까
hashSet은 hashCode를 고유한 식별자로 사용해 검색 최적화를 한다.
객체의 hashCode를 비교하고 해시 코드가 같은 경우에만 실제 값을 비교한다.
그러면 우리는 위의 경우 어떻게 오버라이드 해야할까.
class Product(val categoryLabel: String, val name: String =""){
override fun hashCode(): Int{
return categoryLabgel.hashCode() + name.hashCode()
}
위와 같이 오버라이드 하면 결과가 true가 된다.
결론적으로 data를 관리하는 class일 경우 toString, equals, hashCode를 오버라이드해야한다.
class Product(val categoryLabel: String, val name: String =""){
override fun toString(): String{
~~~
}
override fun equals(other: Any): Boolean{
~~~
}
override fun hashCode(): Int{
return categoryLabgel.hashCode() + name.hashCode()
}
코틀린을 사용할 때 class 앞에 data 키워드를 추가하면 위 3가지 함수를 오버라이드 하지 않아도 된다.
when을 사용할 때 특징이 나타난다.
fun log(e: Error) = when(e) {
is FileReadError -> { println("Error while reading file ${e.file}") }
is DatabaseError -> { println("Error while reading from database ${e.source}") }
RuntimeError -> { println("Runtime error") }
// the `else` clause is not required because all the cases are covered
}
모든 경우를 포함할 경우 else가 필요 없다.
https://codechacha.com/ko/kotlin-sealed-classes/
https://kotlinworld.com/m/165
https://kotlinlang.org/docs/sealed-classes.html#sealed-classes-and-when-expression