Sealed Class

woga·2021년 4월 7일
0

Android 공부

목록 보기
2/49

Sealed Class란?

enum 클래스의 확장형태로 클래스들을 묶은 클래스이다.


그럼 왜 enum의 확장형태가 나오게 됐을까?

enum은 여러 제약사항이 있다.

  • 각각의 enum 상수에 대해 하나의 인스턴스만 생성할 수 있다.
  • 주어진 enum에 대한 상태를 변경할 수 없다.
  • enum에 대한 서브클래스를 생성할 수 없다.

이런 제약들 떄문에 내가 만약 색깔 enum 클래스에 검정, 빨강, 초록 말고도 다른 색깔을 추가해서 0번째로 쓰고 싶어도 검정이 항상 0인 상태가 된다.

즉, sealed class는 위의 제약사항을 보완한 클래스라고 생각하면 된다.


Sealed Class의 기본 원칙

  • Sealed 클래스는 클래스 이름 앞에 sealed 키워드를 붙여 만들 수 있다.
  • Sealed 클래스의 서브클래스들은 반드시 같은 파일 내에 선언되어야 한다.
  • Sealed 클래스는 기본적으로 abstract 클래스이다.
  • Sealed 클래스는 prviate 생성자만 갖는다.
  • Sealed 클래스의 서브 클래스를 상속한 클래스들은 아무곳이나 존재해도 상관없다. 같은 파일 내에 없어도 된다.

예시

Month는 Sealed 클래스고 서브 클래스들을 갖고 있는 형태

sealed class Month {
    data class January(val monthIndex: Int, val shortForm: String) : Month()
    data class February(val monthIndex: Int, val shortForm: String, val noOfDays: Int) : Month()
    data class March(val monthIndex: Int, val shortForm: String) : Month()
    data class April(val monthIndex: Int, val shortForm: String) : Month()
    data class May(val monthIndex: Int, val shortForm: String) : Month()
    data class June(val monthIndex: Int, val shortForm: String) : Month()
    data class July(val monthIndex: Int, val shortForm: String) : Month()
    data class August(val monthIndex: Int, val shortForm: String) : Month()
    data class September(val monthIndex: Int, val shortForm: String) : Month()
    data class October(val monthIndex: Int, val shortForm: String) : Month()
    data class November(val monthIndex: Int, val shortForm: String) : Month()
    data class December(val monthIndex: Int, val shortForm: String) : Month()
}

interface 형태를 가진다면?

interface Month { fun days() }

class June() : Month { override fun days() {} }
class August() : Month { override fun days() {} }

fun calculate(controller: Month) = when (controller) {
		is June -> 30
    	is August -> 31
    	else -> 0 //else절 필수
    }

Sealed 클래스 방식으로 활용한다면?

sealed class Month { abstract fun days() }

class June() : Month { override fun days() {} }
class August() : Month { override fun days() {} }

fun calculate(controller: Month) = when (controller) {
		is June -> 30
    	is August -> 31
    	//else절 필수 x
    }

or

sealed class Month {
	class June() : Month { fun days() {} }
	class August() : Month { fun days() {} }
}

fun calculate(controller: Month) = when (controller) {
		is Month.June -> 30
    	is Month.August -> 31
    }

예시로 보는 Sealed Class 이점

  • Sealed class의 서브클래스에 대해 여러개의 인스턴스 생성 가능
  • Sealed class의 계층 생성 가능
  • when 구문을 사용한다면 Sealed class에서 else 절 구현 필요 없음

공식 문서 속 설명

Sealed classes represent restricted class hierarchies that provide more control over inheritance. All subclasses of a sealed class are known at compile time. No other subclasses may appear after a module with the sealed class is compiled. For example, third-party clients can't extend your sealed class in their code. Thus, each instance of a sealed class has a type from a limited set that is known when this class is compiled.

To declare a sealed class, put the sealed modifier before its name.

sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()

Reference

etc

추가로 보면 좋은 것

profile
와니와니와니와니 당근당근

0개의 댓글