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

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


# 前回の復習と今回の概要
一旦、復習代わりにもう一度背景を書きます。

```kotlin 
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クラスとして統合して扱うために、

```kotlin
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だったのでした。

つまり、

```kotlin 
data class PBook(var id : Long, var name : String, var kakaku : Int)
data class EBook(var id : Long, var name : String, var kakaku : Int)
```
ではなくて、

```kotlin
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にして、

```kotlin
sealed class Book : Parcelable {
    class PBOOK(val pBook : PBook) : Book()
    class EBOOK(val eBook : EBook) : Book()
}
```
のようにしたいのですが、Parcelableを、どう実装することになるのでしょうか？というのが本記事の趣旨です。

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

```kotlin
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にするには以下のようにします。

```kotlin
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](http://grandstaish.github.io/paperparcel/)を導入してsealedクラスをParcelabeにしてみたいと思います。
特にインナークラスの実装がPaperParcelでは、どうなるかが肝となります。