我想“锁定”一个从特征扩展而来的类。斯卡拉有可能吗?
例如我有:
trait A {
val boris: String
val john: String
val number: Int
}
class B extends A {
// do something with these values
}
但是我可以确保,如果没有在特征 A 中声明新值,那么在 B 类中不会添加新值?
感谢您的回答。
我想“锁定”一个从特征扩展而来的类。斯卡拉有可能吗?
例如我有:
trait A {
val boris: String
val john: String
val number: Int
}
class B extends A {
// do something with these values
}
但是我可以确保,如果没有在特征 A 中声明新值,那么在 B 类中不会添加新值?
感谢您的回答。
你不能。
但是,如果您只是将特征标记为密封并提供默认实现:
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 中——简单地锁定所有内容并让用户以这种方式丰富原始界面。
不过,我不确定这是否涵盖了您的预期用例;它不提供任何继承。
根据您的示例和我对您实际尝试做的事情的猜测,您可能需要考虑仅使用案例类。
通常避免扩展案例类(我认为如果您尝试它会发出弃用警告),这样会阻止人们想要扩展您的类以添加功能。
将您的示例转换为案例类:
case class A (boris: String, john: String, number: Int)
然后,您无需扩展A
以更改其值,而是创建一个新实例,例如
val a2 = someOtherA.copy(john="Doe")