给出以下代码:
abstract class Foobar {
type Parent <: Foobar
def parent: Option[Parent]
}
class Foo extends Foobar {
type Parent = Nothing
val parent = None
// ***
// Taking the explicit declaration of the "bar" method's return type
// "Bar" away convinces Scala to compile the code. In other words:
//
// def bar() = new Bar
// ***
def bar(): Bar = new Bar {
type Parent = Foo
val parent = Some(Foo.this)
}
}
abstract class Bar extends Foobar
(new Foo).bar().parent.get.bar()
我的问题:
你能解释一下为什么会这样吗?请参阅上面的内联评论。
您有解决方案吗?
我在版本3.0.2-vfinal-20131028-1923-Typesafe中从Scala-SDK的Scala工作表中收到以下错误消息:
Multiple markers at this line
- value bar is not a member of scrap.Bar#Parent
- value bar is not a member of scrap.Bar#Parent
好的,省略“bar”方法的返回类型声明会从Scala工作表中留下以下信息:
> res0: scrap.Bar{type Parent = scrap.Foo; val parent: Some[scrap.Foo]} = scra
//| p$Foo$$anon$1@3bba229e
有没有办法给这个类型一个像样的名字,理想情况下是“Foobar#Parent”?
答案 0 :(得分:1)
中会发生什么
(new Foo).bar().parent.get.bar()
是:
new Foo
是Foo
.bar()
中的Foo
属于Bar
类型(声明如此,即使实际结果超过此值).parent
中的Bar
未重新定义,父级也未重新定义,因此只有parent: Parent <: FooBar
从FooBar继承。将使用绑定的FooBar
。 bar
,因此.parent.bar()
失败。 如果你在Foo中声明
def bar(): Bar { type Parent = Foo} = new Bar {// same as your code}
或只是
def bar() = new Bar {// same }
让推断类型,它工作正常。
如果您声明def bar(): Bar
,那么这就是输入停止的地方。就像您声明def bar(): Any = whatever
一样,它不会考虑whatever
的类型。并且Foo
的子类型将被允许返回具有不同Bar
类型的Parent
。
关于您的更新:
我不确定为什么我希望将该类型显示为FooBar#Parent
,这几乎没有任何说明,但无论如何,我认为你不能说服scala这样做。
简单显示的简单方法是命名您返回的类型,而不是匿名扩展Bar
。如果你不想这样做,你至少要声明方法的返回类型,这无论如何都是好的做法。否则,scala将以最大精度显示它所推断的内容。你可以使用def Bar: Bar {type Parent = Foo} = ...
,或者你可以为它声明一个类型别名(最好是在Foo之外):
type BarWithFooParent : Bar {type Parent = Foo }
def bar(): BarWithFooParent = new Bar() { … }