请查看以下示例:
trait MyTrait {
def myTraitMeth : String
}
object TraitImplementation extends MyTrait {
def myTraitMeth = "Works fine"
def myExtraMeth = "Doesn't work"
}
case object Manager {
def returnImplementation : MyTrait = TraitImplementation
}
println(Manager.returnImplementation.myExtraMeth)
在这种情况下,发生的事情是我无法访问特质实现TraitImplementation
的额外方法,因为我将方法returnImplementation
的返回方法定义为类型MyTrait
-我无法更改此条件。
一个明显的解决方案是在trait上强制使用这种额外的方法,但是考虑到MyTrait
的其他实现不能拥有这样的方法,这对我来说不是一个选择。
我真正需要的是确保方法returnImplementation
返回的是MyTrait
的实现,并同时允许该方法的调用者使用所有方法已经实施的,不仅是在特质上实施的。
我尝试弄乱类型,使用
case object Manager {
def returnImplementation [A <: MyTrait] : A = TraitImplementation
}
但这会导致类型不匹配,因为编译器无法理解A是泛型类型。
关于如何实现它的任何想法?
答案 0 :(得分:0)
我本来想发表评论,但由于正在进行讨论,所以空间变得有些拥挤。我决定将其写为答案。
您遇到的这个问题听起来像可以通过使用大小写匹配来解决。当returnImplementation返回一个MyTrait类型的特征时,对其进行大小写匹配以获取所需的子类,并且取决于它是哪个子类,它们具有不同的行为。如果您想要单子快速失败行为,请将其包装在Option中,以便仅某些子类将触发某些结果的创建。如果找到具有所需方法的所需子类,则结果为Some(...),否则为None。
trait MyTrait {
def myTraitMeth : String
}
object TraitImplementation extends MyTrait {
def myTraitMeth = "Works fine"
def myExtraMeth = "Doesn't work"
}
case object Manager {
def returnImplementation : MyTrait = TraitImplementation
}
对于您的println语句,您可以这样称呼它:
Manager.returnImplementation match {
case TraitImplementation => println(TraitImplementation.myExtraMeth)
case _ =>
}
如果您想保持代码的纯功能性而没有诸如println函数之类的副作用,请执行以下操作:
val result = Manager.returnImplementation match {
case TraitImplementation => Some(TraitImplementation)
case _ => None
}
result
的类型为Option [TraitImplementation],您可以将其传递给上下文相关行为。
如果您有副作用代码(例如println语句),则可以通过在此Option上调用foreach来将其与其余纯函数代码隔离开来,如下所示:
result.foreach(x => println(x.myExtraMeth))
根据您和Luis的讨论,您还可以在MyExtTrait上进行大小写匹配,以实现所需的行为。
trait MyExtTrait {
def myExtraMeth: String
}
val result = Manager.returnImplementation match {
case x: MyExtTrait => println(x.myExtraMeth)
case _ =>
}
或
val result = Manager.returnImplementation match {
case x: MyExtTrait => Some(x)
case _ => None
}
result.foreach(x => println(x.myExtraMeth))