另一种方法是使用枚举类。相对于地图的优势在于您拥有可以直接在代码中引用的数据结构,因此您可以使用HerbData.Dill 和HerbData["Dill"]。这将使您能够利用编译时检查和 lint 警告、重构、详尽的模式匹配、代码完成等,因为数据是在您的代码中定义的
enum class HerbData(
val herbName: String,
val scientificName: String? = null,
val dullThumbnail: Int? = null
) {
Dill("This is Dill!", "Anethum Graveolens", R.drawable.dill_thumbnail_attr),
Peppermint("This is Peppermint!");
companion object {
operator fun get(name: String): HerbData? =
try { valueOf(name) } catch(e: IllegalArgumentException) { null }
}
}
fun main() {
// no guarantee these lookups exist, need to null-check them
HerbData["Peppermint"]?.herbName.run(::println)
// case-sensitive so this fails
HerbData["peppermint"]?.herbName.run(::println)
// this name is defined in the type system though! No checking required
HerbData.Peppermint.herbName.run(::println)
}
>> This is Peppermint!
null
This is Peppermint!
Enum 类有 valueOf(String) 方法,可以让您按名称查找常量,但如果没有匹配项,它会抛出异常。我将它添加为类中的get 运算符函数,因此您可以像地图一样使用典型的getter 访问(例如HerbData["Dill"])。作为替代方案,您可以做一些更整洁的事情:
companion object {
// storing all the enum constants for lookups
private val values = values()
operator fun get(name: String): HerbData? =
values.find() { it.name.equals(name, ignoreCase = true) }
}
您可以调整效率(我只是存储 values() 的结果,因为该调用每次都会创建一个新数组)但这很简单 - 您只是存储所有枚举条目并创建一个查找根据名称。如果需要,这可以让您变得更聪明一些,例如使查找不区分大小写(这可能是也可能不是一件好事,具体取决于您这样做的原因)
这里的优点是您自动生成查找 - 如果您重构枚举常量的名称,字符串标签将始终匹配它(您可以使用枚举常量本身的 name 属性获取)。当然,代码中的任何“Dill”字符串都将保留为“Dill”——这是使用硬编码字符串查找的限制
真正的问题是,您为什么要这样做?如果它是纯数据,不需要在代码中显式引用任何项目,并且它们都在运行时查找,那么您可能应该使用数据类和映射,或者类似的东西。如果您确实需要在编译时将它们作为代码中的对象引用(并且尝试使用 HerbData."Dill".herbName 意味着您这样做),那么枚举是一种相当简单的方法让您同时做到这一点