对于这两个代码块,我希望两个块中的self
引用都是Foo [A]。但是似乎第二个块没有编译。有人可以向我解释如何解决self
引用吗?
trait Foo[A] {
def format(value:A):String
def bar[B](f:B=>A):Foo[B] = {
val self = this
new Foo[B] {
override def format(value: B): String = self.format(f(value))
}
}
}
trait Foo[A] {
def format(value:A):String
val self = this
def bar[B](f:B=>A):Foo[B] = {
new Foo[B] {
override def format(value: B): String = self.format(f(value))
}
}
}
答案 0 :(得分:2)
self
被赋予this
,这是对特定实例的引用,是您在调用时调用方法(或构造函数)的实例。
在第一个代码段中,您在bar
类型的对象上调用方法Foo[A]
,这意味着此时this
表示Foo[A]
的实例。在将this
分配给self
之后,您将继续创建Foo
的新实例,这次为type参数指定了不同的类型,但self
。
在第二个代码段中,您说类型Foo[A]
的对象有一个名为self
的成员字段,并被分配this
。无论您如何调用type参数,这都将适用于Foo[_]
的所有实例。当您创建第二个Foo
调用类型参数B
时,第二个实例仍会有一个成员字段self
,该字段将被分配this
,此时此字段为{ {1}}和阴影您在Foo[B]
的初始声明中声明的self
。
这意味着在第二个代码段中,Foo
format
方法实现可以访问Foo[B]
本身的self
引用,这会导致类型错误提及。
Foo[B]
采用一个bar
并将其转换为B
A
应用于f: B => A
,将其变为value: B
,然后尝试将A
提供给A
对于错综复杂的回复感到抱歉;简而言之:类型参数仅仅是实际类型的占位符名称,就像值参数是实际运行时值的占位符名称一样。将相同的推理应用于类型和值,并且对它们的推理将变得更容易。