0

我想“锁定”一个从特征扩展而来的类。斯卡拉有可能吗?

例如我有:

trait A {
val boris: String
val john: String
val number: Int
}

class B extends A {
 // do something with these values
}

但是我可以确保,如果没有在特征 A 中声明新值,那么在 B 类中不会添加新值?

感谢您的回答。

4

2 回答 2

4

你不能。

但是,如果您只是将特征标记为密封并提供默认实现:

sealed trait A { val boris: String }
final class B(val boris: String) extends A {}

然后人们可以自由地创建隐式值类,使其看起来像是添加了新功能(除非没有实际创建类):

implicit class MyB(val underlying: B) extends AnyVal {
  def sirob = underlying.boris.reverse
}
(new B("fish")).sirob   // "hsif"

如果你想在编译时(虽然不是运行时)保持它们的直接,你也可以让类将类型参数作为标记:

sealed trait A[T] { val boris: String }
final class B[T](val boris: String) extends A[T] {}

implicit class MyB(val underlying: B[Int]) extends AnyVal {
  def sirob = underlying.boris.reverse
}
(new B[Int]("fish")).sirob   // "hsif"
(new B[Char]("fish")).sirob  // error: value sirob is not a member of B[Char]

因此,您可以——尤其是在 2.10 中——简单地锁定所有内容并让用户以这种方式丰富原始界面。

不过,我不确定这是否涵盖了您的预期用例;它不提供任何继承。

于 2013-01-24T20:27:13.110 回答
0

根据您的示例和我对您实际尝试做的事情的猜测,您可能需要考虑仅使用案例类。

通常避免扩展案例类(我认为如果您尝试它会发出弃用警告),这样会阻止人们想要扩展您的类以添加功能。

将您的示例转换为案例类:

case class A (boris: String, john: String, number: Int)

然后,您无需扩展A以更改其值,而是创建一个新实例,例如

val a2 = someOtherA.copy(john="Doe")
于 2013-01-24T21:28:00.717 回答