「Enum」ってなんだ? - いまさら聞けないKotlinのなぜ

「Enum」ってなんだ? – いまさら聞けないKotlinのなぜ

ENGINEER.CLUB編集部

ENGINEER.CLUB編集部

KotlinのEnum(列挙型)とは、複数の定数をまとめて扱うことができる便利な記法のことです。クラスの様に扱えますが、オブジェクトとなっていてインスタンス化できません。またEnumを使用すれば処理の抜け漏れの検知や共通化することもできます。

そんなEnumについて本記事では解説していくので一緒に学んでいきましょう。


1.Enumとは

Enumとはenumerationの略で列挙、羅列、枚挙等の意味を持ち、定数(オブジェクト)のリストを保持する特別なクラス型です。KotlinではJavaと同様にEnumが使用できます。


2.Enumの基本

ここではEnumの宣言方法と利用例について解説していきます。

2-1.Enumの宣言

Enumを宣言する方法を見ていきましょう。

■Enumの宣言方法解説

まずKotlinEnum宣言を記述するには、以下の様にEnum宣言と共にクラス名を書き、列挙型となるEnum定数を並べて書いていきます。

enum class Enumクラス名 {
	Enum定数, ・・・;
}

■具体例

enum class PhoneBook {
    POLICE,RESCUE,TIMESIGNAL;
}

定数は一般的に大文字を使いますので、それにならって記述しましょう。

2-2.Enumの利用例

Enumの定数を使用する時は“Enumクラス名.Enum定数の形で利用できます。

またwhen文の入力にEnumを使用すれば、各条件にEnum定数全てが使用されているかIDEにてチェックが入り、処理の抜け漏れの検知がされます。

fun main() {
    val phoneBook = PhoneBook.RESCUE;
    parse(phoneBook)//消防です
}

enum class PhoneBook {
    POLICE,
    RESCUE,
    TIMESIGNAL;
}

fun parse(phoneBook: PhoneBook) {
    when (phoneBook) {
        PhoneBook.POLICE -> println("警察です")
        PhoneBook.RESCUE -> println("消防です")
        PhoneBook.TIMESIGNAL -> println("時報です")//例えばこの行が抜けていた場合IDEで警告が表示される。
    }
}

3.Enumの応用

ここではEnumにある様々な機能について見ていきましょう。

3-1. Enumの暗黙のメソッド・プロパティの仕様

Enumクラスには様々な暗黙のメソッド・プロパティが定義されています。

■プロパティ一覧

[Enum定数の暗黙のプロパティ]
| プロパティ | 説明 |
| Enum定数.name | Enum定数の文字列を返します |
| Enum定数.ordinal | Enum定数の位置を返します |

■使用例

fun main() {
    println("${PhoneBook.POLICE.name}:${PhoneBook.POLICE.ordinal}")//POLICE:0
    println("${PhoneBook.RESCUE.name}:${PhoneBook.RESCUE.ordinal}")//RESCUE:1
    println("${PhoneBook.TIMESIGNAL.name}:${PhoneBook.TIMESIGNAL.ordinal}")// TIMESIGNAL:3
}

・・・

■メソッド一覧

[列挙型の暗黙のメソッド]
| メソッド | 説明 |
| valueOf | 引数としてEnum定数名を取って、Enum型を返します |
| values | Array型として全Enum定数を返します |

後述のプログラムにて使用しますので動作を見てみましょう。

3-2. Enumにコンストラクタ、フィールド、メソッドを追加

Enumにコンストラクタ・フィールド・メソッドを追加する方法を見ていきましょう。

■コンストラクタとフィールドの設定例

クラス名の後ろに括弧を付けることでコンストラクタが設定できます。そして括弧の中にフィールドを持つこともできます。

fun main(args: Array) {//実行時引数入力値:POLICE
    val telClass = TelClass.valueOf(args[0])
    println(telClass.phoneNo);//110
}

enum class TelClass(val phoneNo: Int) {
    POLICE(110),
    RESCUE(119),
    TIMESIGNAL(117);
}

■メソッド追加例1

クラス内で抽象メソッドを宣言すれば、Enum定数上で実装することができます。

fun main(args: Array) {//実行時引数:TIMESIGNAL
    val telClass = TelClass2.valueOf(args[0])
    telClass.talk()//現在4時00分をお知らせします。
}

enum class TelClass2 {
    POLICE {
        override fun talk() = "事件ですか?事故ですか?"
    },
    RESCUE {
        override fun talk() = "消防ですか?救急ですか?"
    },
    TIMESIGNAL {
        override fun talk() = "現在4時00分をお知らせします。"
    };

    abstract fun talk(): String
}

■メソッド追加例2

Enumクラスへ実装する物としてインターフェースを継承させることができます。ちなみにEnumクラスはオブジェクトとなるため他に継承させることはできません。また各Enum定数で共通化した処理を行う“ans()”メソッド、Enumクラスで使用できる“of()”メソッドを用意しています。

fun main() {
    println("電話番号を入力してください。")
    val telTo = readLine()?.let { TelProc.of(it.toInt()) }
        ?: throw RuntimeException()
    //"119"を入力
    telTo.takeIf { !it.isChoose() }
        ?.let { println(it.talk()[0]) }
        ?: telTo.let {
            it.talk().forEachIndexed { index, str -> print("${index}:$str ") }
            //0:消防ですか? 1:救急ですか? 
            println("\r\n0から${it.comeCarType().size - 1}の中のいずれかを選択してください。")
            //0から1の中のいずれかを選択してください。
            readLine()?.toInt()?.let { num -> println(it.ans(num)) }
            //"0"を入力
            //消防車を呼びます、少々お待ちください。
        }
}

interface Tel {
    fun talk(): List
    fun isChoose(): Boolean
    fun comeCarType(): List
    fun ans(itemIndex: Int): String
}

enum class TelProc(val phoneNo: Int) : Tel {
    POLICE(110) {
        override fun talk() = listOf("事件ですか?", "事故ですか?")
        override fun isChoose() = true
        override fun comeCarType() = listOf("パトカー", "白バイ")
    },
    RESCUE(119) {
        override fun talk() = listOf("消防ですか?", "救急ですか?")
        override fun isChoose() = true
        override fun comeCarType() = listOf("消防車", "救急車")
    },
    TIMESIGNAL(117) {
        override fun talk() = listOf("現在4時00分をお知らせします。")
        override fun isChoose() = false
        override fun comeCarType() = emptyList()
    };

    override fun ans(itemIndex: Int): String =
        comeCarType()[itemIndex] + "を呼びます、少々お待ちください。"

    companion object {
        fun of(phoneNo: Int) = values().first { it.phoneNo == phoneNo }
    }
}

4.EnumをJavaと相互運用するときのtips

先ほどの例でcompanion objectが出てきましたが、JavaからKotlinのクラスを呼ぶ場合は“TelProc.Companion.of(hoge)”となってしまいます、そこで以下のようにメソッドに“@JmvStatic”をつけることで“TelProc.of(hoge)”と呼び出すことができます。

enum class TelProc(val phoneNo: Int) : Tel {
    ...
    
    companion object {
    	@JvmStatic
        fun of(phoneNo: Int) = ...
    }
}

5.さいごに

これで皆さんEnumマスターに成れましたね。Enumを使用する事で複数の値を効率良くまとめられます。ここで学んだことをぜひご活用ください。

私たちは、全てのエンジニアに市場価値を高め自身の望む理想のキャリアを歩んでいただきたいと考えています。もし、今あなたが転職を検討しているのであればこちらの記事をご一読ください。理想のキャリアを実現するためのヒントが見つかるはずです。

『技術力』と『人間力』を高め市場価値の高いエンジニアを目指しませんか?

私たちは「技術力」だけでなく「人間力」の向上をもって遙かに高い水準の成果を出し、関わる全ての人々に感動を与え続ける集団でありたいと考えています。

高い水準で仕事を進めていただくためにも、弊社では次のような環境を用意しています。

  • 定年までIT業界で働くためのスキル(技術力、人間力)が身につく支援
  • 「給与が上がらない」を解消する6ヶ月に1度の明確な人事評価制度
  • 平均残業時間17時間!毎週の稼動確認を徹底しているから実現できる働きやすい環境

現在、株式会社ボールドでは「キャリア採用」のエントリーを受付中です。

まずは以下のボタンより弊社の紹介をご覧いただき、あなたの望むキャリアビジョンをエントリーフォームより詳しくお聞かせください。

コメント

公式アカウントLINE限定!ボールドの内定確率が分かる無料診断実施中
公式アカウントLINE限定!
ボールドの内定確率が分かる無料診断実施中