gpt4 book ai didi

kotlin - Kotlin 中的密封类是什么?

转载 作者:IT老高 更新时间:2023-10-28 13:34:36 27 4
gpt4 key购买 nike

我是 Kotlin 的初学者,最近阅读了 Sealed Classes .但是从文档中我真正得到的唯一想法是它们是存在的。

文档指出,它们“代表受限的类层次结构”。除此之外,我发现他们是具有超能力的枚举。这两个方面其实都不清楚。

那么你能帮我解决以下问题吗:

  • 什么是密封类以及使用它们的惯用方式是什么?
  • 这样的概念是否存在于 Python、Groovy 或 C# 等其他语言中?

更新:我仔细检查了这个blog post仍然无法理解这个概念。如帖子所述

Benefit

The feature allows us to define class hierarchies that arerestricted in their types, i.e. subclasses. Since all subclasses needto be defined inside the file of the sealed class, there’s no chanceof unknown subclasses which the compiler doesn’t know about.

为什么编译器不知道其他文件中定义的其他子类?甚至 IDE 都知道这一点。只需按 Ctrl+Alt+B例如,在 IDEA 中,List<>即使在其他源文件中也将显示定义和所有实现。如果一个子类可以定义在一些第三方框架中,而应用程序中没有使用,我们为什么要关心呢?

最佳答案

假设您有一个域(您的宠物),您知道其中有明确的类型枚举(计数)。例如,您有两个且只有两个宠物(您将使用名为 MyPet 的类对其进行建模)。 Meowsi 是你的猫,Fido 是你的狗。

比较该人为示例的以下两个实现:

sealed class MyPet
class Meowsi : MyPet()
class Fido : MyPet()

因为你使用了密封类,当你需要根据宠物的类型来执行一个 Action 时,那么MyPet的可能性就一分为二了,你可以确定MyPet 实例将恰好是以下两个选项之一:

fun feed(myPet: MyPet): String {
return when(myPet) {
is Meowsi -> "Giving cat food to Meowsi!"
is Fido -> "Giving dog biscuit to Fido!"
}
}

如果你不使用密封类,那么可能性并没有穷尽两种,你需要包含一个 else 语句:

open class MyPet
class Meowsi : MyPet()
class Fido : MyPet()

fun feed(myPet: MyPet): String {
return when(myPet) {
is Mewosi -> "Giving cat food to Meowsi!"
is Fido -> "Giving dog biscuit to Fido!"
else -> "Giving food to someone else!" //else statement required or compiler error here
}
}

换句话说,没有密封类,就没有穷尽(完全覆盖)的可能性。

请注意,您可以使用 Java enum 实现穷尽可能性,但这些并不是完全成熟的类。例如 enum 不能是另一个类的子类,只能实现一个接口(interface)(感谢 EpicPandaForce )。

完全耗尽可能性的用例是什么?打个比方,假设您的预算很紧,而且您的饲料非常珍贵,并且您希望确保最终不会喂食不属于您家庭的额外宠物。

没有 sealed 类,你家/应用程序中的其他人可以定义一个新的 MyPet:

class TweetiePie : MyPet() //a bird

并且这个不想要的宠物将由您的 feed 方法喂养,因为它包含在 else 语句中:

       else -> "Giving food to someone else!" //feeds any other subclass of MyPet including TweetiePie!

同样,在您的程序中耗尽可能性是可取的,因为它减少了您的应用程序可能处于的状态数量,并减少了在您可能处于行为定义不明确的状态时发生错误的可能性。

因此需要 sealed 类。

其他必填项

请注意,如果将 when 用作表达式,您只会获得强制性的 else 语句。根据文档:

If [when] is used as an expression, the value of the satisfied branch becomes the value of the overall expression [... and] the else branch is mandatory, unless the compiler can prove that all possible cases are covered with branch conditions

这意味着你不会因为这样的事情而获得密封类的好处):

fun feed(myPet: MyPet): Unit {
when(myPet) {
is Meowsi -> println("Giving cat food to Meowsi!") // not an expression so we can forget about Fido
}
}

要在这种情况下耗尽精力,您需要将语句转换为具有返回类型的表达式。

Some 建议使用这样的扩展功能会有所帮助:

val <T> T.exhaustive: T
get() = this

那么你可以这样做:

fun feed(myPet: MyPet): Unit {
when(myPet) {
is Meowsi -> println("Giving cat food to Meowsi!")
}.exhaustive // compiler error because we forgot about Fido
}

Others 建议扩展函数会污染命名空间,因此需要其他解决方法(如编译器插件)。

有关此问题的更多信息,请参见 here

关于kotlin - Kotlin 中的密封类是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50772328/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com