LoginSignup
2
1

More than 5 years have passed since last update.

Android開発においてKotlinでsealedを使った代数データ(直和)型のクラスをParcelableにする話。

Posted at

趣旨

前回の記事でsealedを使った代数データ(直和)型を書きました。
Android開発においてActivity間などアプリ内で情報を流通させるのにデータクラスをParcelableに
しておくと何かと都合が良いですが、sealedを使ったクラスをParcelableにします。
もう少し具体的に書くと、もともとParcelableだったクラス(前回の記事でいうと、PBookとEBookクラス)を統合して代数データ型のクラス(前回の記事のBookクラス)にして、その統合クラス自体もParcelbleにするというのが今回の記事です。
もともとParcelableは、冗長でテンプレ的な側面を持っており、Parcelableを簡素に記述するためのライブラリなどもありますが、それは次回の予定記事としたいと思います。
今回は、まずは実直にParcelableを実装してみます。

前回の復習と今回の概要

一旦、復習代わりにもう一度背景を書きます。

data class PBook(var id : Long, var name : String, var kakaku : Int)
data class EBook(var id : Long, var name : String, var kakaku : Int)

の既存クラスに手を入れずにBookクラスとして統合して扱うために、

sealed class Book {
    class PBOOK(val pBook : PBook) : Book()
    class EBOOK(val eBook : EBook) : Book()
}

としました。ちなみに、前回の記事ではBookクラスにはtitle, priceプロパティやunwrapメソッドを書いてましたが、今回のParcelable化の記事では焦点がぼやけるため省略しています。

今回の記事の肝

前回はAndroid開発に限らないKotlin言語の記事として書いたため既存クラスをParcelableでないものとして記述していましたが、記事の元ネタとなった実際のAndroid開発ではParcelableだったのでした。

つまり、

data class PBook(var id : Long, var name : String, var kakaku : Int)
data class EBook(var id : Long, var name : String, var kakaku : Int)

ではなくて、

data class PBook(var id : Long, var name : String, var kakaku : Int) : Parcelable { ...省略... }
data class EBook(var id : Long, var name : String, var kakaku : Int) : Parcelable { ...省略... }

でした。

このとき、前回の記事で統合したBookクラスもParcelableにして、

sealed class Book : Parcelable {
    class PBOOK(val pBook : PBook) : Book()
    class EBOOK(val eBook : EBook) : Book()
}

のようにしたいのですが、Parcelableを、どう実装することになるのでしょうか?というのが本記事の趣旨です。

ちなみに、PBookを例にとってParcelbleの実装をきちんと記述すると

data class PBook(var id : Long,
                 var name : String,
                 var kakaku : Int) : Parcelable {
    constructor(parcel: Parcel) : this(
            parcel.readLong(),
            parcel.readString(),
            parcel.readInt())

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeLong(id)
        parcel.writeString(name)
        parcel.writeInt(kakaku)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<PBook> {
        override fun createFromParcel(parcel: Parcel): PBook {
            return PBook(parcel)
        }

        override fun newArray(size: Int): Array<PBook?> {
            return arrayOfNulls(size)
        }
    }
}

のようになります。面倒ですね、Parcelable。

結論

さて、BookクラスをParcelableにするには以下のようにします。

sealed class Book : Parcelable {
    class PBOOK(var pBook : PBook): Book() {
        constructor(parcel: Parcel) : this(parcel.readParcelable<PBook>(PBook::class.java.classLoader))
        override fun writeToParcel(parcel: Parcel, flags: Int) {
            parcel.writeParcelable(pBook, flags)
        }

        override fun describeContents(): Int {
            return 0
        }

        companion object CREATOR : Parcelable.Creator<PBOOK> {
            override fun createFromParcel(parcel: Parcel): PBOOK {
                return PBOOK(parcel)
            }

            override fun newArray(size: Int): Array<PBOOK?> {
                return arrayOfNulls(size)
            }
        }
    }

    class EBOOK(var eBook : EBook) : Book() {
        constructor(parcel: Parcel) : this(parcel.readParcelable<EBook>(EBook::class.java.classLoader))

        override fun writeToParcel(parcel: Parcel, flags: Int) {
            parcel.writeParcelable(eBook, flags)
        }

        override fun describeContents(): Int {
            return 0
        }

        companion object CREATOR : Parcelable.Creator<EBOOK> {
            override fun createFromParcel(parcel: Parcel): EBOOK {
                return EBOOK(parcel)
            }

            override fun newArray(size: Int): Array<EBOOK?> {
                return arrayOfNulls(size)
            }
        }
    }
}

Bookクラスは、抽象クラスになるので、Parcelableを実装するのは、具象クラスのBook.PBOOKとBook.EBOOKクラスということになります。
ぼんやりと眺めるとPBookとEBookクラスのParcelbleの実装をしているように見えますが、あくまでもラッパー側のBook.PBOOKとBook.EBOOKの実装をしています。
これで、BookクラスもParcelableになり、Androidの中でActivityやFrafmentを越えて書籍情報を流通させることができるようになりました。
しかし、なんて面倒臭いのでしょう。ここでPaperParcelを導入するともっと楽に記述できるのですが。。。。

つづく

ということで、次はParparParcelを導入してsealedクラスをParcelabeにしてみたいと思います。
特にインナークラスの実装がPaperParcelでは、どうなるかが肝となります。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1