Menu
Coddy logo textTech

Enumクラス

CoddyのKotlinジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 33/57。

enum class は値の集合が固定された型を宣言します。この値は定数です。各定数は、name と ordinal(0 から始まる位置)を持つ enum のオブジェクトです。entries はそれらを順番に一覧表示します。

enum class Direction { NORTH, EAST, SOUTH, WEST }

main の中で:

val d = Direction.EAST
println(d)
println(d.ordinal)
println(Direction.entries)

出力:

EAST
1
[NORTH, EAST, SOUTH, WEST]

enum の定数にはプロパティを持たせて enum のコンストラクターに渡すことができ、enum はメソッドを宣言できます。セミコロンはメンバーの前で定数のリストを終了します。

enum class Coin(val cents: Int) {
    PENNY(1), NICKEL(5), DIME(10), QUARTER(25);

    fun label() = "${name.lowercase()} ($cents c)"
}

main の内部:

println(Coin.DIME.label())
println(Coin.entries.sumOf { it.cents })

出力:

dime (10 c)
41

すべての定数を列挙する enum に対する when では else は必要なく、コンパイラーは不足している定数を報告します。valueOf("SOUTH") は完全一致する名前で定数を検索し、未知の名前に対しては例外をスローするため、入力には通常 entries.find を使って照合します。

enum class Direction { NORTH, EAST, SOUTH, WEST }

fun turnRight(d: Direction) = when (d) {
    Direction.NORTH -> Direction.EAST
    Direction.EAST -> Direction.SOUTH
    Direction.SOUTH -> Direction.WEST
    Direction.WEST -> Direction.NORTH
}

fun parse(text: String) = Direction.entries.find { it.name == text.uppercase() }

main の中で:

println(turnRight(Direction.valueOf("SOUTH")))
println(parse("north"))
println(parse("up"))

出力:

WEST
NORTH
null

定数は独自の本体を持ち、そこでメソッドをオーバーライドできます。列挙型でメソッドを abstract として宣言すると、すべての定数にその実装が強制されます。

enum class Op(val symbol: String) {
    PLUS("+") {
        override fun apply(a: Int, b: Int) = a + b
    },
    TIMES("*") {
        override fun apply(a: Int, b: Int) = a * b
    };

    abstract fun apply(a: Int, b: Int): Int
}

main の中では次のようにします。

for (op in Op.entries) println("6 ${op.symbol} 3 = ${op.apply(6, 3)}")

出力:

6 + 3 = 9
6 * 3 = 18
challenge icon

チャレンジ

簡単

列挙型 Size を、定数 SMALL(250 ml、価格 300)、MEDIUM(350 ml、380)、LARGE(500 ml、450)で完成させてください。価格の単位はセントです。label() は medium (350 ml): 3.80 を返し、upsize() は次に大きいサイズを返します。ただし、LARGE の場合は同じサイズを返します。コンパニオンの parse(text) は、大文字と小文字を区別せずに名前でサイズを検索するか、最初の文字(s、M)で検索し、それ以外の場合は null を返します。

提供されたコードは、medium、L、up small(サイズアップしたドリンク)などの注文を読み取り、各ラベルまたは unknown size x を出力し、最後に total: 11.10 を出力します。

コードは Size.kt に記述してください。Main.kt には提供された入出力コードが含まれており、編集できません。

自分で試してみよう

fun main() {
    // 提供された入出力コード: そのままにしておく
    val input = generateSequence(::readLine).toList()
    var total = 0
    for (line in input) {
        val upsize = line.startsWith("up ")
        val size = Size.parse(line.removePrefix("up "))
        if (size == null) {
            println("unknown size $line")
            continue
        }
        val chosen = if (upsize) size.upsize() else size
        println(chosen.label())
        total += chosen.price
    }
    println("total: %d.%02d".format(total / 100, total % 100))
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Kotlinプレイグラウンド