久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

KotlinのSealed Classを使いこなす

 昵稱27265735 2018-03-27


Sealed Classについて

Sealed Classとは継承を制限して,、階層を明確にできるクラスです,。

詳しくは公式ドキュメントを參照してください,。

Sealed Classes - Kotlin Programming Language

もう少し分かりやすく言うと,、1つのファイル內でだけ継承できるクラスです,。

Sealed Classを使う利點

普通の(final or open)クラスと比べて

外部からの継承を制限できるので、コンパイル時に子クラスの階層が全て明らかになります,。

これで何ができるかというと,、when式とis演算子の組み合わせで網(wǎng)羅性のチェックができます。

例えば下のコードのように、通常の A を継承する B/C/D というクラスがある時に

open class A
class B : A()
class C : A()
class D : A()

このAの子クラスのインスタンスがどのクラスか判定して何か値を返す関數(shù)は

fun isSomething(obj : A) : Boolean {
  return when (obj) {
    is B -> true
    is C -> true
    is D -> false
  }
}

と書くとコンパイルエラーになる(B/C/D以外の可能性がないことを判別できない)ので,、以下のように書くと思います,。

fun isSomething(obj : A) : Boolean {
  return when (obj) {
    is B -> true
    is C -> true
    is D -> false
    else -> throw RuntimeException("Not reached!!!!")
  }
}

elseは(自分達が書いているコード的には)絶対通らないはずだけど、例外を投げるか何らかの値を返す必要があります,。

もちろんこのコードがライブラリーにあったとして,、利用者がAを継承したEというクラスを作って渡すと、このコードはelseに到達しますね,。

Sealed Classにすることで,、コンパイラーがこのAの子クラスはB/C/Dしかないことを知られるので、最初のコードでも問題なくなります,。

こうすることで,、後で自分でAを継承する別のクラスを作ると、ここに選択肢を追加しないとコンパイルが通らなくなり,、処理の追加漏れがなくなります,。

Enumと比べて

前の項で書いている內容は、Enumでも実現(xiàn)できますね,。

Enumと比べてSealed Classを利用する利點は,、「Sealed Classを継承するのはobjectでもclassでもよい」ということではないでしょうか。

Sealed Classの子クラスそれぞれをEnumの値のように扱うことで,、「Enumの各値に可変の値を持たせるような仕組み」ができます,。

SwitftだとAssociated Valueと呼ばれるものですね。

使い方

使い方は簡単で,、class宣言の前にsealedと書き,、子クラスを全て同じファイル內で宣言するだけです。

sealed class A
class B : A()
class C : A()
class D : A()
object Z : A()

こうすることで,、クラスAはこのファイル內でしか継承できなくなります,。

また、Aはabstractなクラスかつ,、コンストラクターがprivateになるので,、直接インスタンス生成はできなくなります。

あとは通常のクラスと同じように使います,。

どういう使い方をしている,?

私が実際にSealed Classを使うシチュエーションを紹介します。

決まった文字列(全てが定數(shù)ではない)を受け取りたい時

これはSealed Classの「ファイル外で継承できない」仕組みを活用する例です,。

例えばAndroidアプリでGoogle Analyticsにスクリーン名を送りたい時,、スクリーンは定められた値なので、大半が定數(shù)で定義可能です,。

しかし,、完全な定數(shù)で済めばいいのですが,、ページングをしている時にパラメーターとしてページ數(shù)を送りたいかもしれません。

また,、普通にStringを送る運用だとミスって意味の分からない文字列を送ってしまうかもしれません,。

こういった場合にそれぞれのスクリーン用にSealed Classを継承したobjectやclassを作り、Google Analyticsの送信用のラッパーを用意して,、そこで値を分解して送るとこの問題を防ぐことができます,。

sealed class GAScreen() {
  abstract val screenName: String

  open class Simple(override val screenName: String) : GAScreen()

  object Top : Simple("top")
  object Settings : Simple("settings")
  object List(private val page: Int) : GAScreen() {
    override val screenName: String = "list[page=$page]"
  }
}

ラッパー側は以下のようになります。

class GoogleAnalyticsWrapper() {
  fun sendScreen(screen: GAScreen) {
    val screenName = screen.screenName
    // ここでスクリーン名を送る
  }
}

こうすることで,、うっかり変な文字列を送ることがなくなります,。

色々な値を受け取って表示するActivityを起動するIntentに渡すパラメーターオブジェクト

こちらは"すごい

Intentに複數(shù)のパラメーターをセットしたい時,、全部を別々に手で受け取るのは面倒ですよね。

そのパラメーターの中にNullableなものがあって,、別のパラメーターの値によって値が入ってなかったりすると思います,。

こういう時にパラメーターオブジェクトを作って、Parcelableにして渡すのが有効と考えられます,。

sealed class MainScreen() {
  object Top : MainScreen()
  object Settings : MainScreen()
  class Feed(val skipTutorial: Boolean) : MainScreen()
  class Category(val category: Category) : MainScreen()
  class EntryList(val initialTab: Tab) : MainScreen()
}

これをActivity側で受け取ってwhen式を使うなどして処理してやります,。

when(screen) {
  is Top -> {
    openTop()
  }
  is Settings -> {
    openSettings()
  }
  is Feed -> {
    openFeed(screen.skipTutorial)
  }
  is Category -> {
    openCategory(screen.category)
  }
  is EntryList -> {
    openEntryList(screen.initialTab)
  }
}

最後に

KotlinのSealed Classを使って堅牢な設計のアプリを作りましょう。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,,所有內容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內容中的聯(lián)系方式,、誘導購買等信息,,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,,請點擊一鍵舉報,。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多