연습장/이론

클래스 1-3. Sealed Class

아이른 2024. 4. 29. 15:07

1. Sealed Class

  • 계층을 나타내기 위한 하나의 용도
  • interface, abstract 클래스를 사용하는 것과 거의 동일
//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에 비해 빠름 (큰 차이는 없음)

 

'연습장 > 이론' 카테고리의 다른 글

클래스 6-1. object  (0) 2024.05.06
클래스 1-2. Data Class 활용  (0) 2024.04.24
Kotlin_ 1-2. 전역변수, 지역변수  (0) 2024.04.11
Kotlin_ 4-3. 확장 함수  (1) 2024.04.02
클래스 1-2. 컬렉션 클래스(Collection class)  (0) 2024.03.11