鉴于
case class Fruit(name: String, colour: String)
我想弃用案例类字段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
弃用,而且我无法找到任何资源。
实际上,我可以使用其他方法实现相同的任务,例如通过将我的case类放宽到普通类并为getter
提供colour
并使后者弃用,但我想知道是否实际上不可能弃用case类字段并且 - 最终 - 原因。
谢谢。
更新
正如Mike正确指出的那样,colour
是案例类的必填字段,因此将此属性设置为deprecated
的意义是有争议的。我想弃用colour
,因为我现在提供来自其他构造的colour
信息,我想让用户知道colour
不是正确的实例通过哪里获取该信息,我将在下一版本中将其从Fruit
中删除。
到目前为止,我只是警告用户不要从Fruit属性中获取colour
信息,暂时,如果他们可以创建带有颜色信息的水果实例,我真的不在乎
更新2
正如Alexey所说,我在编译时确实有不赞成的警告。但是为什么我不能在IDE代码中看到弃用以及我弃用某个方法呢?我期待类似下面的内容
val fruit = Fruit("peer", "green")
val colour = fruit.colour
我正在使用IntelliJ。
答案 0 :(得分:5)
这是一个奇怪的用例。如果必填字段已弃用,那么该类本身也必须已弃用,当然?也就是说,假设您尝试做的事情是可能的,那么在没有获得弃用警告的情况下,无法在所有中使用类。 (这可能解释了为什么它不可能。)
那就是说,正如你所指出的那样,有很多方法可以实现你想要做的事情。这是其中之一:
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
的属性。 (如果 是必需的,则不应该弃用。)它的工作原理是弃用创建Fruit
的工厂方法一个colour
值。
如果这不起作用,您能否解释为什么该字段需要弃用?
答案 1 :(得分:2)
您的第一个版本似乎工作正常:如果您粘贴
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代码内联中显示错误和警告是非常不可靠的,您应该始终通过实际构建项目进行检查。
答案 2 :(得分:0)
这很棘手,它还取决于您想要的兼容性级别。
您可以删除该字段(从而将其从主构造函数中删除),但也可以使用旧签名创建不推荐使用的构造函数。另外,您需要在配对对象上使用类似的apply方法。问题是,它会破坏案例类的模式匹配(除非你覆盖unapply)。也许你觉得它合理,也许不是。而且,如果您不想打破读者,您还必须实现已弃用的getter存根。 (但值得回答的是什么价值。)
更保守的方法:弃用主构造函数,创建没有值的辅助(不推荐)构造函数。此外,弃用该字段。这似乎工作正常,它不会破坏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的参数。