Saya mencoba menemukan cara terbaik untuk melakukan 'pencarian terbalik' pada enum di Kotlin. Salah satu kesimpulan saya dari Java Efektif adalah Anda memperkenalkan peta statis di dalam enum untuk menangani pencarian terbalik. Mem-porting ini ke Kotlin dengan enum sederhana mengarahkan saya ke kode yang terlihat seperti ini:
enum class Type(val value: Int) {
A(1),
B(2),
C(3);
companion object {
val map: MutableMap<Int, Type> = HashMap()
init {
for (i in Type.values()) {
map[i.value] = i
}
}
fun fromInt(type: Int?): Type? {
return map[type]
}
}
}
Pertanyaan saya adalah, apakah ini cara terbaik untuk melakukan ini, atau ada cara yang lebih baik? Bagaimana jika saya memiliki beberapa enum yang mengikuti pola serupa? Apakah ada cara di Kotlin untuk membuat kode ini lebih dapat digunakan kembali di seluruh enum?
Jawaban:
Pertama-tama, argumen dari
fromInt()
haruslah anInt
, bukanInt?
. Mencoba mendapatkanType
menggunakan null jelas akan menghasilkan null, dan penelepon bahkan tidak boleh mencoba melakukan itu. ItuMap
juga tidak memiliki alasan untuk bisa berubah. Kode dapat dikurangi menjadi:Kode itu sangat pendek sehingga, sejujurnya, saya tidak yakin apakah perlu mencoba menemukan solusi yang dapat digunakan kembali.
sumber
fromInt
pengembalian non-null sepertiEnum.valueOf(String)
:map[type] ?: throw IllegalArgumentException()
by lazy{}
untukmap
dangetOrDefault()
untuk akses yang lebih aman olehvalue
Type.fromInt()
dari kode Java, Anda perlu memberi anotasi pada metode@JvmStatic
.kita bisa menggunakan
find
yang Mengembalikan elemen pertama yang cocok dengan predikat yang diberikan, atau null jika tidak ada elemen yang ditemukan.sumber
first { ... }
karena tidak ada gunanya untuk banyak hasil.first
bukanlah peningkatan karena mengubah perilaku dan melemparNoSuchElementException
jika item tidak ditemukan di manafind
yang sama denganfirstOrNull
pengembaliannull
. jadi jika Anda ingin membuang alih-alih mengembalikan penggunaan nolfirst
fun valueFrom(valueA: Int, valueB: String): EnumType? = values().find { it.valueA == valueA && it.valueB == valueB }
Anda juga dapat membuat pengecualian jika nilainya tidak ada dalam enum:fun valueFrom( ... ) = values().find { ... } ?: throw Exception("any message")
atau Anda dapat menggunakannya saat memanggil metode ini:var enumValue = EnumType.valueFrom(valueA, valueB) ?: throw Exception( ...)
Tidak masuk akal dalam kasus ini, tetapi berikut adalah "ekstraksi logika" untuk solusi @ JBNized:
Secara umum, itulah hal tentang objek pendamping yang dapat digunakan kembali (tidak seperti anggota statis di kelas Java)
sumber
Opsi lain, yang dapat dianggap lebih "idiomatis", adalah sebagai berikut:
Yang kemudian bisa digunakan seperti
Type[type]
.sumber
Saya menemukan diri saya melakukan pencarian terbalik dengan kustom, kode tangan, nilai beberapa kali dan datang dengan pendekatan berikut.
Make
enum
s mengimplementasikan antarmuka bersama:Antarmuka ini (betapapun aneh namanya :)) menandai nilai tertentu sebagai kode eksplisit. Tujuannya agar bisa menulis:
Yang dapat dengan mudah dicapai dengan kode berikut:
sumber
Varian dari beberapa proposal sebelumnya mungkin adalah sebagai berikut, menggunakan ordinal field dan getValue:
}
sumber
Contoh implementasi lainnya. Ini juga menyetel nilai default (di sini untuk
OPEN
) jika tidak ada input yang cocok dengan opsi enum:}
sumber
Hadir dengan solusi yang lebih umum
Contoh penggunaan:
sumber
Cara Kotlin Idiomatik Sejati. Tanpa kode refleksi kembung:
sumber
val t = Type.values () [ordinal]
:)
sumber