Home > OS >  Kotlin enum like in the swift
Kotlin enum like in the swift

Time:03-03

I have enum in swift

enum Type {
    case bool(Bool)
    case int(Int)
    case array([String])
}

Dont understand how i can convert this to kotlin code, i did like this:

enum class AnswerSheetType {
    BOOL,
    INT,
    ARRAY
}

But how i can pass variable to enum type. For example then i want create method which will be return type with variable, like this(swift code):

func marks(for id: String) -> Type {
    let answer = answers?[id]
    
    if let boolAnswer = answer as? Bool {
        return .bool(boolAnswer)
    }
    if let intAnswer = answer as? Int {
        return .int(intAnswer)
    }
    if let arrayAnswer = answer as? [String] {
        return .array(arrayAnswer)
    }
}

CodePudding user response:

You can use a sealed interface/class to represent this.

sealed interface Type {

    data class BoolType(val value: Bool) : Type
    data class IntType(val value: Int) : Type
    data class ArrayType(val value: Array<String>) : Type

    // if you have a case that doesn't have any associated values, just use an object
    // object CaseWithoutAssociatedValues: Type

}

Usage:

// let someType: Type = .bool(true)
val someType: Type = Type.BoolType(true)

// just like how you can use a switch on a Swift enum, you can use a when like this too:
// This when is also exhaustive, if you specify all the implementers of Type
when (someType) {
    is Type.BoolType -> println("Bool value: ${someType.value}")
    is Type.IntType -> println("Int value: ${someType.value}")
    is Type.ArrayType -> println("Array value: ${someType.value}")
}

Notice that in each of the branches, you can access someType.value, because of the smart-cast. This is unlike in Swift, where you would do pattern matching to get the associated values out.

CodePudding user response:

As I was writing my answer Sweeper already answered with almost the identical solution. I wanted to add to that, that your marks function could then be written as this:

fun marks(id: String) : Type? {
    when (val answer = answers?.get(id)) {
        is Boolean -> return Type.BoolType(answer)
        is Int -> return Type.IntType(answer)
        is Array<*> -> if (answer.isArrayOf<String>()) return Type.ArrayType(answer as Array<String>)
    }
    return null
}

The Array case is a bit ugly but that is because checking on is Array<String> is not possible. The IDE will also still complain about having an unchecked cast but it should work. I don't know if there's a nicer way to handle this.

  • Related