//Interface
interface TestResult
class Pass(val grade: Int) : TestResult
class Fail(val grade: Int, val reason: String) : TestResult
fun main() {
val grade = 100
val testResult: TestResult
if (grade == 100)
testResult = Pass(grade = grade)
else
testResult = Fail(grade = grade, reason = "게임하느라...")
println(testResult) //Pass@3a71f4dd
}
//Abstract class
abstract class TestResult
class Pass(val grade: Int) : TestResult()
//() 차이: 클래스이기 때문에 클래스 객체를 생성해서 상속
class Fail(val grade: Int, val reason: String) : TestResult()
fun main() {
val grade = 100
val testResult: TestResult
if (grade == 100)
testResult = Pass(grade = grade)
else
testResult = Fail(grade = grade, reason = "게임하느라...")
println(testResult) //Pass@3a71f4dd
}
sealed 클래스 사용
//Abstract class와 동일
sealed class TestResult
class Pass(val grade: Int) : TestResult()
class Fail(val grade: Int, val reason: String) : TestResult()
fun main() {
val grade = 100
val testResult: TestResult
if (grade == 100)
testResult = Pass(grade = grade)
else
testResult = Fail(grade = grade, reason = "게임하느라...")
println(testResult) //Pass@3a71f4dd
}
interface, abstract class는 Non-restricted hierarchy : 모든 하위 클래스를 정의한다는 것이 보장되지 않음
Sealed class는 abstract와 동일하다고 보면되지만 제한된 계층(restricted-hierarchy)를 지원
is Fall/Pass -> TestResult를 상속받는 Fall/Pass는 하위 타입이기 때문에 is를 통해 체크
when문 사용 시,
interface, abstract 사용_ 하위 클래스 일부만 구현 가능
sealed 사용_ 하위 클래스 모두 구현
제한사항 (제한된 계층구조이기 때문 - 안정성 보장)
하위 클래스는 상위 클래스와 같은 package안에 있어야 함
하위 클래스는 상위 클래스와 같은 모듈에 있어야 함
Sealed class vs interface (abstract class vs interface와 같다고 생각)
Sealed class : 상태를 가질 수 있음, 단일 상속
Sealed interface : 상태를 가질 수 없음, 여러 인터페이스를 상속 가능
fun main() {
val success = Success("abc")
println(success.hello())
println(success.data)
}
sealed class Result(val hello: String) {
val helloWorld = "HelloWorld" //helloWorld의 상태를 가짐
}
class Success(val data: String) : Result(hello = "hello") {
//This type has a constructor, and thus must be initialized here
fun hello() {
println(hello)
println(helloWorld)
}
}
//print
hello
HelloWorld
kotlin.Unit //hello() 리턴값이 Unit이기 때문
abc
fun main() {
val failure = Failure()
println(failure) //Failure@6e8cf4c6
}
sealed interface ResultTwo {
val helloWorld: String //상태를 가질 수 없음
}
class Failure : ResultTwo {
override val helloWorld: String
get() = "asdf"
fun hello() {
println(helloWorld)
}
}
Sealed vs Enum
Enum은 상수 or 값들의 집합, Sealed subtype(하위 타입)의 집합
Enum은 모든 값들이 동일한 필드/프로퍼티를 가져야 하지만, Sealed의 경우 원하는 형태대로 하위 타입을 커스터마이징 할 수 있음
주로 Enum은 불변 값을 나타내는 경우, Sealed는 확장가능한 상태값을 나타내는 경우에 많이 사용
Enum은 앱이 끝나기 전까지 상수, Sealed 하위 타입의 경우 참조되지 않는 경우 GC에 의해 제거 (단, object로 선언되어 있으면 Enum과 마찬가지로 GC에 의해 제거되지 않음)
when을 사용할 때 Enum은 단순한 상수비교이므로 “is” check을 통해 타입을 확인하는 sealed에 비해 빠름 (큰 차이는 없음)