嵌套类本身是一个相当直观的概念,即一个概念在逻辑上依赖于另一个更广泛的概念。当您发现自己正在描述一个更广泛概念的构建块,并且不希望它单独出现在您的业务逻辑中时,您会想要声明一个新的嵌套类。因此,这样一个类的实例是通过其所嵌套的类的定义来访问的。
以以下结构为例:
class Parrot(val name: String): Animal {
class HealthyConditions {
val featherColour: String
val cageSize: Size
val weightInGrammes: Int
val dailySleepInHours: Int
fun isUnderweight(currentWeightInGrammes: Int): Boolean {
return currentWeightInGrammes < weightInGrammes
}
}
}
现在,对于任何描述的动物
而言,健康居住条件的概念已经普及并且非常重要,但是针对不同种类的动物,需要考虑多个完全不同的因素。试图为所有这些动物一次性准备一个通用的HealthyConditions<Animal>
类很可能会导致难以维护和阅读的代码,充满了if
s 和 else
s。因此,对于每种Animal
,开发人员定义简明、整洁的嵌套类可能更有意义。将来,它们将通过Parrot.HealthyConditions()
,Cat.HealthyConditions()
等进行访问,而不是通过HealthyConditions.getForSpecies(animal)
。
内部类是基于嵌套类的Kotlin概念。当某些细节非常特定于给定概念时,它们被描述为嵌套类,但如果这些细节根据更广泛的概念实例而变化会怎么样呢?那么仅通过类定义访问它可能不足以正确操作。因此,内部类是通过调用其所属类的实例来访问的。
让我们回到我们的Parrot
吧。
class Parrot(val name: String, var age: Int): Animal {
inner class HealthyConditions {
val featherColour: String
val cageSize: Size
val weightInGrammesByAge: Map<Int, Int>
val dailySleepInHoursByAge: Int<Int, Int>
fun isUnderweight(currentWeightInGrammes: Int): Boolean {
return weightInGrammesByAge[age] > currentWeightInGrammes
}
}
}
健康的鹦鹉应该有多重在其一生中会发生变化。孵化时几百克的重量是可以接受的,但成年个体低于2公斤可能需要注意。因此,是否X克的鹦鹉体重不足不能轻易回答,但如果我们问Bob鹦鹉是否需要增加一些体重,我们可以利用我们了解的关于Bob的知识来确定答案。为了做到这一点,将通过
Parrot("Bob", 5).HealthyConditions()
访问HealthyConditions类。
现在,你可能仍然想知道访问父类属性对内部类是否真的有用。毕竟,在讨论嵌套类时,我们决定每个动物都应该有自己的健康状况实现。对于Dog类,狗的品种与年龄一样重要,以确定其正确的体重。对于其他物种,性别也将非常重要。这意味着,如果内部类无法直接访问其父级属性,则Healthcheck接口的checkIfUnderweight()函数将不得不接受大量不同,可能是可空的变量,以便适用于系统中所有不同类型的动物。
我花了很多时间谈论概念,没有太多的代码示例,但据我所知,您不是在实施方面遇到困难,而是在首次实施代码的理由上。此外,请原谅我所想出的“动物类”示例可能看起来很简单-事实上,这是我想出的第一个。
无论如何,我希望这篇简短的阅读材料能帮助您更好地了解概念及其用例。安全编码,愿错误远离您!
inner
关键字后,将导致编译错误。 - JB Nizetinner
”就好比在Java中省略“static
”。 - Minn