Kotlin의 sealed class를 능숙하게 사용하다
18478 단어 Kotlin
Kotlin은 편리한 언어 기능을 많이 가지고 있습니다.
그중에서 저는 개인적으로
sealed class
를 좋아하기 때문에 이 매력을 소개하고 싶습니다.sealed class
기준 일본을 대표하는 Kotlin 에벤저의 블로그입니다.
한마디로 계승을 제한하는 데 쓰이는 수식부호다.sealed를 가진 클래스를 계승하려면 어떤 조건을 만족시켜야 한다.
kotlin 1.2.1 현재,sealedclass에 삽입된 클래스와 같은 파일에서 설명한 클래스만 계승할 수 있습니다.// in Base.kt
sealed class Base {
object SubOne: Base() // ok
object SubTwo: Base() // ok
}
class SubThree: Base() // ok
// in Other.kt
object SubFour: Base() // ng
그렇군요. 알겠습니다.
그런데 이걸 어떻게 사용해야 좋을까요?
sealedclass의 용도
Kotlin 참조에 따르면 이런 느낌의 용도인 것 같다.
유한 범위 유형 중 하나의 값을 원한다면, 클래스 차원 구조의 범위를 한정하기를 원할 때Sealedclass를 사용합니다.
이것은 enumclass의 확장판과 같다. enum의 상량은 하나의 실례로 존재하지만, sealedclass의 하위 클래스는 여러 개의 실례로 상태가 있을 수 있다.
Sealed classes are used for representing restricted class hierarchies, when a value can have one of the types from a limited set, but cannot have any other type. They are, in a sense, an extension of enum classes: the set of values for an enum type is also restricted, but each enum constant exists only as a single instance, whereas a subclass of a sealed class can have multiple instances which can contain state.
그렇구나, 몰랐어.
그냥 제가 번역을 잘 못했나봐요.
하지만 편리한 사용법이 있습니다.
백문이 불여일견.우리 구체적으로 한번 봅시다.
우리 순서대로 봅시다.
규정된 값을 선택하고 싶지만 사용자 정의 값을 지정하고 싶습니다
참고자료에'확장판 enum 같은 것'이라고 쓰여 있으니 그 인상으로 사용해 보세요.
색상
예를 들어 어떤 색으로 가득 칠하고 싶은지.fun fill(color: Color) {
...
}
Color
사용하기 편리하도록 기본 정의된 몇 가지 색을 준비했습니다. 어떤 경우에는 임의의 값을 받아들일 수 있습니다.
그럼 어떻게 발표해야 좋을까요?
정의된 것 중에서 무엇을 선택할 때 가장 먼저 떠오르는 것은 엔움!우리 먼저 엔움에 성명합시다.
enum class Color {
RED,
GREEN,
BLUE
}
사용자 정의 값은 어떻게 합니까?성명 후,enum 상량은 값을 가질 수 없습니다.
CMYK가 나와도 색상을 지정하려는 주문이 있다면?약간 머리를 안고 있는 것 같은데...
거기서 사용할 수 있는 것은 sealed class입니다.sealed class Color {
// objectは単一インスタンスのみもつクラスを作るキーワード。
// つまりenum定数を作るのとあまり変わらない。
object Red: Color()
object Green: Color()
object Blue: Color()
// 任意のclassがsealed classの子クラスになれるので
// data classでも良い。
data class Rgb(val red: Int, val green, val blue): Color()
data class Cmyk(val cyan: Int, val magenta: Int, val yellow: Int, val keyPlate: Int): Color()
}
상수뿐만 아니라 사용자 정의 값도 표시할 수 있다니.
편리하다!!
가치의 중첩을 표현하고 싶어요.
우리 깊이 생각해 봅시다.
위Color
류는 여러 상태가 겹치는 것으로 포착할 수 없습니까?
특히 데이터class 부분만 꺼내서 보세요.sealed class Color {
data class Rgb(val red: Int, val green, val blue): Color()
data class Cmyk(val cyan: Int, val magenta: Int, val yellow: Int, val keyPlate: Int): Color()
}
이것도'Color
는 색깔(표현법은 모르지만), 색깔의 표현법Rgb
또는Cmyk
'이라고 읽을 수 있다.
형으로 이'또는'을 표현할 수 있는 것은 대수 데이터형이다.
이렇게 이해하면 표현할 수 있는 것들의 범위가 넓어질 것 같지 않아요?
예: 성공 또는 실패
처리된 결과를 호출자에게 되돌려주고 싶다면, 보통return을 사용합니다.
fun doSomeProc(): SomeData {
...
// 結果を返す
return someValue
}
만약 네가 자주 성공한다면 좋겠다.
그러면 실패한 경우는요?반환값이 Int
등이면 -1
이상값을 이상값으로 설정하는 경우도 있지만 자바의 세계에서는 예외를 던진다.
fun doSomeProc(): SomeData {
...
// 失敗した場合は例外を投げて値を返さない
if (failed) throw FailureException()
return someValue
}
하지만 Kotlin은 검사 예외가 없습니다.
실수로 try-catch
를 잊어버리면 실행할 때 예외적인 프로그램도 붕괴될 수 있습니다.
그렇다면 성공과 실패를 가치로 표현해 보는 것은 어떨까?sealed class Result<V>
data class Success<V>(val value: V): Result<V>()
data class Failure<V>(val reason: Exception): Result<V>()
fun doSomeProc(): Result<SomeData> {
...
return if (failed) Failure(FailureException())
else Success(someValue)
}
val result = doSomeProc()
when (result) {
// smart castしてます。便利。
is Success -> println("data is ${result.value}")
is Failure -> println("process failed because ${result.reason}")
}
이렇게 하면 성공할 때와 실패할 때의 행동을 명확하게 쓸 수 있다. is
의 유형 검사가 없으면 안의 값을 꺼낼 수 없기 때문에 성공인지 실패인지 강제로 검사할 수 있다.
여러 명이 개발할 때 편리합니다!
네, 눈치채셨을 거예요. 이른바 에이더형이에요.
좋은 에이서의 설치는 map
등이 있고, 일일이 넣지 않아도 되기 때문에 실용적일 때 유지자가 공개한 라이브러리를 사용하는 것이 좋다.
// in Base.kt
sealed class Base {
object SubOne: Base() // ok
object SubTwo: Base() // ok
}
class SubThree: Base() // ok
// in Other.kt
object SubFour: Base() // ng
Kotlin 참조에 따르면 이런 느낌의 용도인 것 같다.
유한 범위 유형 중 하나의 값을 원한다면, 클래스 차원 구조의 범위를 한정하기를 원할 때Sealedclass를 사용합니다.
이것은 enumclass의 확장판과 같다. enum의 상량은 하나의 실례로 존재하지만, sealedclass의 하위 클래스는 여러 개의 실례로 상태가 있을 수 있다.
Sealed classes are used for representing restricted class hierarchies, when a value can have one of the types from a limited set, but cannot have any other type. They are, in a sense, an extension of enum classes: the set of values for an enum type is also restricted, but each enum constant exists only as a single instance, whereas a subclass of a sealed class can have multiple instances which can contain state.
그렇구나, 몰랐어.
그냥 제가 번역을 잘 못했나봐요.
하지만 편리한 사용법이 있습니다.
백문이 불여일견.우리 구체적으로 한번 봅시다.
우리 순서대로 봅시다.
규정된 값을 선택하고 싶지만 사용자 정의 값을 지정하고 싶습니다
참고자료에'확장판 enum 같은 것'이라고 쓰여 있으니 그 인상으로 사용해 보세요.
색상
예를 들어 어떤 색으로 가득 칠하고 싶은지.
fun fill(color: Color) {
...
}
Color
사용하기 편리하도록 기본 정의된 몇 가지 색을 준비했습니다. 어떤 경우에는 임의의 값을 받아들일 수 있습니다.그럼 어떻게 발표해야 좋을까요?
정의된 것 중에서 무엇을 선택할 때 가장 먼저 떠오르는 것은 엔움!우리 먼저 엔움에 성명합시다.
enum class Color {
RED,
GREEN,
BLUE
}
사용자 정의 값은 어떻게 합니까?성명 후,enum 상량은 값을 가질 수 없습니다.CMYK가 나와도 색상을 지정하려는 주문이 있다면?약간 머리를 안고 있는 것 같은데...
거기서 사용할 수 있는 것은 sealed class입니다.
sealed class Color {
// objectは単一インスタンスのみもつクラスを作るキーワード。
// つまりenum定数を作るのとあまり変わらない。
object Red: Color()
object Green: Color()
object Blue: Color()
// 任意のclassがsealed classの子クラスになれるので
// data classでも良い。
data class Rgb(val red: Int, val green, val blue): Color()
data class Cmyk(val cyan: Int, val magenta: Int, val yellow: Int, val keyPlate: Int): Color()
}
상수뿐만 아니라 사용자 정의 값도 표시할 수 있다니.편리하다!!
가치의 중첩을 표현하고 싶어요.
우리 깊이 생각해 봅시다.
위
Color
류는 여러 상태가 겹치는 것으로 포착할 수 없습니까?특히 데이터class 부분만 꺼내서 보세요.
sealed class Color {
data class Rgb(val red: Int, val green, val blue): Color()
data class Cmyk(val cyan: Int, val magenta: Int, val yellow: Int, val keyPlate: Int): Color()
}
이것도'Color
는 색깔(표현법은 모르지만), 색깔의 표현법Rgb
또는Cmyk
'이라고 읽을 수 있다.형으로 이'또는'을 표현할 수 있는 것은 대수 데이터형이다.
이렇게 이해하면 표현할 수 있는 것들의 범위가 넓어질 것 같지 않아요?
예: 성공 또는 실패
처리된 결과를 호출자에게 되돌려주고 싶다면, 보통return을 사용합니다.
fun doSomeProc(): SomeData {
...
// 結果を返す
return someValue
}
만약 네가 자주 성공한다면 좋겠다.그러면 실패한 경우는요?반환값이
Int
등이면 -1
이상값을 이상값으로 설정하는 경우도 있지만 자바의 세계에서는 예외를 던진다.
fun doSomeProc(): SomeData {
...
// 失敗した場合は例外を投げて値を返さない
if (failed) throw FailureException()
return someValue
}
하지만 Kotlin은 검사 예외가 없습니다.실수로
try-catch
를 잊어버리면 실행할 때 예외적인 프로그램도 붕괴될 수 있습니다.그렇다면 성공과 실패를 가치로 표현해 보는 것은 어떨까?
sealed class Result<V>
data class Success<V>(val value: V): Result<V>()
data class Failure<V>(val reason: Exception): Result<V>()
fun doSomeProc(): Result<SomeData> {
...
return if (failed) Failure(FailureException())
else Success(someValue)
}
val result = doSomeProc()
when (result) {
// smart castしてます。便利。
is Success -> println("data is ${result.value}")
is Failure -> println("process failed because ${result.reason}")
}
이렇게 하면 성공할 때와 실패할 때의 행동을 명확하게 쓸 수 있다. is
의 유형 검사가 없으면 안의 값을 꺼낼 수 없기 때문에 성공인지 실패인지 강제로 검사할 수 있다.여러 명이 개발할 때 편리합니다!
네, 눈치채셨을 거예요. 이른바 에이더형이에요.
좋은 에이서의 설치는
map
등이 있고, 일일이 넣지 않아도 되기 때문에 실용적일 때 유지자가 공개한 라이브러리를 사용하는 것이 좋다.그러고 보니 Kotlin1.3부터 Kotlin-stdlib은 정식으로 Result형을 채택했다!
편리한 전용 확장 함수 등도 정의되어 있으니 잘 사용하세요!
예: 상태 관리
성공과 실패, 두 개를 합칠 수 있다면 여러 상태도 합칠 수 있다.
응용 프로그램의 화면에서 곤란한 것은 여러 개의 비동기 처리가 도망갈 수 있다는 것이다.
예를 들어 데이터를 읽는 과정에서 또 읽기 이벤트가 발생하면...?
when
또는 읽을 표지판은 무엇입니까?그러면 읽기 중인 상태의 디스플레이 테스트를 하려면 어떻게 해야 하나요?로고는 언제 설치합니까?만약 네가 이런 것들을 고려하기 시작한다면, 너의 머리는 펑크가 날 것이다.
거기서 sealed class!
응용 프로그램의 화면 상태를 관리하는 데도 사용할 수 있습니다!
이것도 내가 사용하기에 매우 편리하고 sealedclass를 좋아하는 이유이다.
// 何かのデータを読み込んで、それを表示する画面の状態管理クラス
class SomeScreenModel(private val repo: Repository, initState: State = State.NoData) {
sealed class State {
// まだ読み込みしていない状態
object NoData: State()
// 読み込み中
object Loading: State()
// 読み込み正常終了
data class Loaded(val hoge: String, val fuga: Int): State()
// 読み込み失敗
data class LoadFailure(val reason: Throwable): State()
}
// RxJavaのObservableや、JavaFXのObservableValueなどで変更を通知できるようにしておくと更に便利
private val subject = BehaviorSubject.createDefault(initState)
val stateChangeEvent: Observable<State>
get() = subject
var currentState: State
get() = subject.value
// 読み込む
fun load() {
// メンバのままだと値が変わる可能性がありsmart castが働かないので、一度取り出しておく
val currentState = currentState
// 読み込み中だったら無視
if (currentState is State.Loading) return
subject.onNext(State.Loading)
repo
.load()
.subscribe({ value ->
subject.onNext(State.Loaded(value.hoge, value.fuga))
}, { e ->
// 例えば失敗を告げるダイアログだけ表示させてから
subject.onNext(State.LoadFailure(e))
// 未読み込み状態に戻るとか
subject.onNext(State.NoData)
})
}
}
이것만으로도 다음과 같은 내용을 실현할 수 있다.화면 디버깅이 상당히 간단해졌다!
안드로이드의 이런 상태 관리 방법은 이전 학습회에서 말했듯이 구체적인 설치 방법은 이쪽 슬라이드를 보십시오.
끝내다
이러한 언어 기능 외에도 experimental의 Kotlin Android Extensions의 기능과 Kotlin/Native 등이 있어 Kotlin의 매력은 더욱 커질 것이다.
내년에도 즐거운 Kotlin 생활 되세요!Have a nice kotlin!!
Reference
이 문제에 관하여(Kotlin의 sealed class를 능숙하게 사용하다), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/kikuchy/items/ad89a12029082be8d218
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(Kotlin의 sealed class를 능숙하게 사용하다), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/kikuchy/items/ad89a12029082be8d218텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)