我正在尝试使用类型变量和结构类型作为学习Scala' cake'图案。
下面是一个玩具API,说明了我的问题:
当结构类型中定义的方法' B'是那些人的超集 结构类型' A',为什么我不能将B的实例传递给想要' A'?
的方法... Toy API ....
object Tester extends App {
trait SomeApi {
type Organism <: {
def die(): Unit;
}
type Dog <: {
def die(): Unit;
def bark(): Unit;
}
def dieQuietlyDoesntCompile(entity: Organism): Unit = {
entity.die()
}
def dieQuietly(entity: { def die(): Unit }): Unit = {
entity.die()
}
def processDog(dog: Dog): Unit = {
println("start dog process on : " + dog)
dieQuietly(dog)
}
}
}
我的API中的结构类型从您可能称之为“基本类型”的内容开始。 (以上例子中的生物),加上,我 在API中有其他类型扩展基类型。在Toy API的情况下,Dog拥有Organism的所有方法,以及 还有一个:&#39; bark()&#39;。
我想编写一些辅助方法来操作基类型,如图所示 processDog()方法....这需要一个&#39; Dog&#39;例如,但也想呼唤“悄悄地”#39;哪一个 处理更通用的类型&#39;有机体&#39;。
我上面做的事情的方式是有效的,但它真的很笨重,因为我必须完全重复所有的方法 基础结构类型。在这个玩具案例中并没有那么糟糕(因为我只有一个方法:die()),但是这些结构类型中的方法数量真的很尴尬 增加。
因此,我宁愿将dog实例传递给类似&#39; dieQuietlyDoesntCompile()&#39;的方法。
但是,正如函数名称所示,如果我将它传递给Dog实例,则无法编译错误:
类型不匹配;发现:dog.type(具有底层类型 SomeApi.this.Dog)需要:SomeApi.this.Organism
有人能建议更方便的方法来实现我的目标吗?或者我不能重复基类型中的方法? (这种方法对我来说似乎不太干)。在此先感谢您的帮助 ! /克里斯
答案 0 :(得分:2)
您的问题是您使用绑定类型<:
来定义Dog
和Organism
。您使用die()
方法将它们约束为类的子类,这使它们不相关。
让我用常规类型来说明它:
trait Mortal // suppose this trait is analogue of { def die():Unit }
class Organism extends Mortal
class Dog extends Mortal
def die(o:Organism) {}
die(new Dog) // obviously will not compile
通过定义Organism
没有类型边界:
type Organism = {
def die(): Unit;
}
答案 1 :(得分:0)
扩大Aivean的答案:
当结构类型中定义的方法&#39; B&#39;是结构类型的超集者&#39; A&#39;为什么我不能将B的实例传递给想要&#39; A&#39;?
的方法?
你可以,但在这种情况下,他们不是。 Organism
不是结构类型,它是一个抽象类型成员,需要是结构类型的子类型。 SomeApi
的一种可能实现是
class ApiImpl extends SomeApi {
type Organism = {
def die(): Unit
def live(): Unit
}
type Dog = {
def die(): Unit
def bark(): Unit
}
override def dieQuietlyDoesntCompile(entity: Organism): Unit = {
entity.live()
}
}
希望您能在Dog
传递给dieQuietlyDoesntCompile
这里的原因显而易见;但这也意味着你无法在原案件中通过它,或者你可以做到
val api: SomeApi = new ApiImpl
val dog: api.Dog = ...
api.dieQuietlyDoesntCompile(dog)