코틀린 언어 정리 2-8

sealed class

개요

enum class와 비슷하지만 더 확장된 개념입니다. enum class는 열거형이 모두 동일한 class이고 instance(객체)는 1개만 생성되며, 선언한 객체가 변경 불가능하지만(상수의 개념) sealed class는 상위 클래스만 같은 서로 다른 형태의 클래스를 선언할 수 있고 다수의 객체를 생성할 수 있으며, 각각 상태를 가질 수 있습니다. 추상 클래스( abstract class )를 상속받는 하위 클래스 집합과 크게 차이가 없지만 sealed class로 선언하면 통상적인 상속 관계에는 없던, 목적에 맞는 제약이 생깁니다.



용도(목적)

sealed class 중심으로 설계된 제한된 클래스 계층(집합)을 전체적으로 표현하고 관리하기 쉽게 합니다. 구체적으로는, sealed class 타입으로 선언한 변수가 참조할 수 있는 class 계층을 제한합니다. 즉 일반적인 클래스들과 마찬가지로 이 타입으로 선언된 변수가 sealed class를 상속받는 하위 클래스들만 참조할 수 있도록 제한할 때 사용됩니다. 여기까지는 일반적인 클래스들과 다른 것이 없습니다.

하지만 이 목적을 위해 sealed class에는 일반 클래스에 없는, 클래스를 선언하는 위치에 대한 제한이 있습니다.

sealed class의 하위 클래스들을 하나의 파일에서 관리하도록 제한 하므로, sealed class와 하위 클래스들을 한번에 쉽게 볼 수 있어 개념적으로 그룹화 하고, 초기 설계 의도와 맞지 않는 하위 클래스의 추가를 방지하는데 도움을 줍니다.

예를 들면, sealed class와 하위 클래스 집합의 설계 목적과 관련 없는 위치(소스파일)에서, 어떤 문제 해결을 위해 sealed class 그룹 전체를 고려하지 않은 채 임시 방편으로 sealed class를 상속 받아 사용하지 말라는 암묵적인 가이드라인을 제시하는 효과가 있습니다.



제약/특징

  • sealed class 자체는 abstract 이므로 직접 생성할 수 없습니다.

  • sealed class는 하위 클래스를 가질 수 있으며 하위 클래스는 모두 sealed class와 같은 파일에 있어야 합니다.

  • 로컬 클래스에서 상속할 수 없습니다.

  • sealed class의 생성자는 private으로 선언해야 됩니다.

  • sealed class의 하위 클래스를 상속받는 클래스는 sealed class와 같은 파일에 있지 않아도 됩니다.

  • when 식과 사용될 때 약간 특수하게 동작합니다.

    • when을 표현식으로 사용하려면 else와 같이 사용해야 하는데 when에 입력된 객체의 실제 타입(주로 하위 타입)의 종류를 알아내기 위해 sealed class를 입력하는 경우, 모든 하위 타입을 체크하는 경우라면 else를 사용하지 않아도 됩니다. else를 사용하지 않는 경우 하위 타입이 늘어날 때마다 하위 타입을 체크하는 when 식에서 에러를 발생시켜 주므로 새로 추가된 type에 대한 처리를 하지 않아 발생할 실행시간 오류를 방지할 수 있는 효과가 있습니다.



사용 방법

sealed class 형의 변수를 선언하고 이를 상속 받은 하위 클래스들 중 하나를 선택하여 객체를 생성합니다.


예제

sealed class Person(var name: String, var age: Int) {

   // sealed class의 하위 클래스는 모두 같은 파일 내에 선언해야 합니다.

   class Student(name: String, age: Int, var grade: Int) : Person(name, age) {}

   class Baby(name: String, age: Int, var parent: Person) : Person(name, age) {}

   class Worker(name: String, age: Int, var company: String) : Person(name, age) {}

   class Senior(name: String, age: Int, var welfareCenter: String) : Person(name, age) {}

}


class Homeless(name: String, age: Int, var position: Int) : Person (name, age) {}


fun main(args: Array<String>) {

//fun test() {

   var person: Person = Person.Worker("Max", 30, "Mad Company")

   if (person is Person.Worker)

       println("${person.name} ${person.age} ${person.company}")

   else

       println("${person.name} ${person.age}")


   // sealed class의 하위 클래스를 모두 명시하는 경우 else를 사용하지 않아도 컴파일 에러가 발생하지 않는다.

   var objNum = when (person) {

       is Person.Student -> 1

       is Person.Baby -> 2

       is Person.Worker -> 3

       is Person.Senior -> 4

       is Homeless -> 5

//        else -> 5

   }

   println(objNum)

}




'코틀린( Kotlin )' 카테고리의 다른 글

코틀린 2-10 Anonymous inner class( object expression )  (0) 2020.04.07
코틀린 2-9 Nested / Inner class  (0) 2020.04.06
코틀린 2-7 enum class  (0) 2020.04.06
코틀린 2-6 data class  (0) 2020.04.05
코틀린 2-5 interface  (0) 2020.04.05

+ Recent posts