Given the following code:
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()
My questions:
Can you explain why this is happening? See inline comment above.
Do you have a solution for this?
I'm getting the following error message from Scala-SDK's Scala Worksheet in version 3.0.2-vfinal-20131028-1923-Typesafe:
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
OK, leaving out the "bar" method's return type declaration leaves me with the following info message from the Scala Worksheet:
> res0: scrap.Bar{type Parent = scrap.Foo; val parent: Some[scrap.Foo]} = scra
//| p$Foo$$anon$1@3bba229e
Is there a way to give this type a decent name, ideally "Foobar#Parent"?
What happens in
is :
new Foo
isFoo
.bar()
inFoo
is of typeBar
(declared so, even if the actual result is more than that).parent
inBar
is not redefined, neither is Parent, so it is justparent: Parent <: FooBar
inherited from FooBar. The boundFooBar
will be used.bar
in FooBar, so.parent.bar()
fails.If you declare in Foo
or simply
letting the type be inferred, it works fine.
If you declare
def bar(): Bar
, this is where the typing stops. Just as if you declaredef bar(): Any = whatever
, it will not consider the type ofwhatever
. And a subtype ofFoo
would be allowed to return aBar
with a differentParent
type.Regarding your update : I 'm not sure why I would want to have that type displayed as
FooBar#Parent
, which tells close to nothing, but anyway, I don't think you can persuade scala to do that.The easy way to have a simple display would be to name the type you return there rather than anonymously extend
Bar
. If you don't want to do that, you have at least to declare the return type of the method, which is good practice anyway. Otherwise, scala will display what it infers, with maximum precision. You can usedef Bar: Bar {type Parent = Foo} = ...
, or you may declare a type alias for that (preferably, outside Foo) :