实际上可以弃用 Scala case class 字段吗?
Is actually possible to deprecate Scala case class fields?
给定
case class Fruit(name: String, colour: String)
我想弃用 class 字段 colour
。
我试图通过同时使用 Scala 来实现前者 @deprecated
case class Fruit(name: String, @deprecated("message", "since") colour: String)
和Java @Deprecated
注释
case class Fruit(
name: String,
/* @Deprecated with some message here */
@(Deprecated @field)
colour: String
)
不幸的是,无论如何我都无法使 colour
弃用,而且我找不到任何关于它的资源。
事实上,我可以使用其他方法来完成相同的任务,例如通过将我的案例 class 放宽到正常 class 并为 colour
提供 getter
并弃用后者,但我想知道是否弃用案例 class 字段实际上是不可能的 - 最终 - 原因。
谢谢。
更新
正如 Mike 正确指出的那样,colour
是案例 class 的必填字段,因此将此属性设置为 deprecated
的意义是有争议的。我想弃用 colour
,因为我现在提供来自另一个构造的 colour
信息,我想让用户知道 colour
不是正确的实例信息,我将在下一版本中将其从 Fruit
中删除。
到现在为止,我只想警告用户不要从 Fruit 属性中获取 colour
信息,而且暂时我真的不在乎他们是否可以创建带有颜色信息的水果实例。
更新 2
正如 Alexey 所说,我在编译时确实收到了弃用警告。但是,为什么我不能观察到 IDE 代码中的弃用以及我弃用的方法呢?我期待类似下面的内容
val fruit = Fruit("peer", "green")<br>val colour = fruit.<strike>colour</strike>
我正在使用 IntelliJ。
这是一个奇怪的用例。如果必填字段 deprecated,那么 class 本身也必须 deprecated,对吧?也就是说,假设您尝试做的事情是可能的,那么在没有收到弃用警告的情况下根本不可能使用 class 。 (这可能解释了为什么不可能。)
就是说,正如您所指出的,有多种方法可以实现您的目标。这是其中之一:
case class Fruit(name: String) {
@deprecated("message", "since")
val colour: String = "some default value"
}
object Fruit {
// Deprecated factory method.
@deprecated("message", "since")
def apply(name: String, colour: String): Fruit = Fruit(name)
}
显然,这假定 colour
不再需要作为 Fruit
的属性。 (如果 是 必需的,则不应 弃用 。)它通过弃用 工厂方法 来工作使用 colour
值创建 Fruit
。
如果这不起作用,您能否解释为什么需要 弃用?
你的第一个版本似乎工作正常:如果你粘贴
case class Fruit(name: String, @deprecated("message", "since") colour: String)
println(Fruit("", "").colour)
在 https://scastie.scala-lang.org/,您会看到弃用警告。当然,你需要访问该字段,无论是直接还是通过提取器:
Fruit("", "") match { case Fruit(x, y) => y }
也会警告。
IDEA 没有显示 colour
已弃用,我认为这只是一个错误。一般来说,在 Scala 代码内联中显示错误和警告是非常不可靠的,你应该始终通过实际构建项目来检查。
这很棘手,它还取决于您想要的兼容性级别。
您可以删除该字段(从而将其从主构造函数中删除),但也可以使用旧签名创建一个已弃用的构造函数。此外,您还需要对伴随对象使用类似的应用方法。问题是,它会破坏 case class 的模式匹配(除非你重写 unapply)。也许你觉得合理,也许不合理。而且,如果您不想打扰读者,您还必须实施已弃用的 getter 存根。 (然而,return 的价值值得怀疑。)
一种更保守的方法:弃用主构造函数,创建一个没有值的辅助 (non-deprecated) 构造函数。另外,弃用该字段。这似乎工作正常,并且不会破坏 unapply 方法。它似乎会按照您的意愿提出弃用警告,除了定义也会引发弃用警告。请参阅此片段:
case class Foo @deprecated() (x: String, @deprecated y: Int){
def this(x: String) = this(x, 0)
}
object Foo {
def apply(x: String) = new Foo(x)
}
println((new Foo("x")).x)
println((new Foo("x", 66)).x)
println((Foo("x")).x)
println((Foo("x", 66)).x)
println((new Foo("x")).y)
println((new Foo("x", 66)).y)
println((Foo("x")).y)
println((Foo("x", 66)).y)
不幸的是,还有no @SuppressWarning。
当然可以根据需要调整@deprecated参数。
给定
case class Fruit(name: String, colour: String)
我想弃用 class 字段 colour
。
我试图通过同时使用 Scala 来实现前者 @deprecated
case class Fruit(name: String, @deprecated("message", "since") colour: String)
和Java @Deprecated
注释
case class Fruit(
name: String,
/* @Deprecated with some message here */
@(Deprecated @field)
colour: String
)
不幸的是,无论如何我都无法使 colour
弃用,而且我找不到任何关于它的资源。
事实上,我可以使用其他方法来完成相同的任务,例如通过将我的案例 class 放宽到正常 class 并为 colour
提供 getter
并弃用后者,但我想知道是否弃用案例 class 字段实际上是不可能的 - 最终 - 原因。
谢谢。
更新
正如 Mike 正确指出的那样,colour
是案例 class 的必填字段,因此将此属性设置为 deprecated
的意义是有争议的。我想弃用 colour
,因为我现在提供来自另一个构造的 colour
信息,我想让用户知道 colour
不是正确的实例信息,我将在下一版本中将其从 Fruit
中删除。
到现在为止,我只想警告用户不要从 Fruit 属性中获取 colour
信息,而且暂时我真的不在乎他们是否可以创建带有颜色信息的水果实例。
更新 2
正如 Alexey 所说,我在编译时确实收到了弃用警告。但是,为什么我不能观察到 IDE 代码中的弃用以及我弃用的方法呢?我期待类似下面的内容
val fruit = Fruit("peer", "green")<br>val colour = fruit.<strike>colour</strike>
我正在使用 IntelliJ。
这是一个奇怪的用例。如果必填字段 deprecated,那么 class 本身也必须 deprecated,对吧?也就是说,假设您尝试做的事情是可能的,那么在没有收到弃用警告的情况下根本不可能使用 class 。 (这可能解释了为什么不可能。)
就是说,正如您所指出的,有多种方法可以实现您的目标。这是其中之一:
case class Fruit(name: String) {
@deprecated("message", "since")
val colour: String = "some default value"
}
object Fruit {
// Deprecated factory method.
@deprecated("message", "since")
def apply(name: String, colour: String): Fruit = Fruit(name)
}
显然,这假定 colour
不再需要作为 Fruit
的属性。 (如果 是 必需的,则不应 弃用 。)它通过弃用 工厂方法 来工作使用 colour
值创建 Fruit
。
如果这不起作用,您能否解释为什么需要 弃用?
你的第一个版本似乎工作正常:如果你粘贴
case class Fruit(name: String, @deprecated("message", "since") colour: String)
println(Fruit("", "").colour)
在 https://scastie.scala-lang.org/,您会看到弃用警告。当然,你需要访问该字段,无论是直接还是通过提取器:
Fruit("", "") match { case Fruit(x, y) => y }
也会警告。
IDEA 没有显示 colour
已弃用,我认为这只是一个错误。一般来说,在 Scala 代码内联中显示错误和警告是非常不可靠的,你应该始终通过实际构建项目来检查。
这很棘手,它还取决于您想要的兼容性级别。
您可以删除该字段(从而将其从主构造函数中删除),但也可以使用旧签名创建一个已弃用的构造函数。此外,您还需要对伴随对象使用类似的应用方法。问题是,它会破坏 case class 的模式匹配(除非你重写 unapply)。也许你觉得合理,也许不合理。而且,如果您不想打扰读者,您还必须实施已弃用的 getter 存根。 (然而,return 的价值值得怀疑。)
一种更保守的方法:弃用主构造函数,创建一个没有值的辅助 (non-deprecated) 构造函数。另外,弃用该字段。这似乎工作正常,并且不会破坏 unapply 方法。它似乎会按照您的意愿提出弃用警告,除了定义也会引发弃用警告。请参阅此片段:
case class Foo @deprecated() (x: String, @deprecated y: Int){
def this(x: String) = this(x, 0)
}
object Foo {
def apply(x: String) = new Foo(x)
}
println((new Foo("x")).x)
println((new Foo("x", 66)).x)
println((Foo("x")).x)
println((Foo("x", 66)).x)
println((new Foo("x")).y)
println((new Foo("x", 66)).y)
println((Foo("x")).y)
println((Foo("x", 66)).y)
不幸的是,还有no @SuppressWarning。
当然可以根据需要调整@deprecated参数。