I am trying to use case objects' types as abstract types. I was surprised to see (similar) code below compiles:
sealed abstract class Bar
case object BarOne extends Bar
case object BarTwo extends Bar
sealed abstract class Foo {
type A <: Bar
def f: A
}
object Foo {
object FooOne extends Foo {
type A = BarOne.type
val f = BarTwo
}
object FooTwo extends Foo {
type A = BarTwo.type
val f = BarOne
}
}
In my real example Foo
is parametrized and used as a case class. So I can't just make A
a type parameter.
How does f = BarTwo
compile, when A
is set to be BarOne.type
?
If A
in f: A
is interpreted as A <: Bar
, why is that so?
Is there a way to concretely set A
for each object instance of Foo
?
I am using Scala 2.11.8.
Update: when I replace val attributeType = ...
with def attributeType = ...
in FooOne
& FooTwo
compilation fails (as expected).
Has anyone suggested you upgrade to a modern version of Scala? (Joke.)
The error about the override gives a nice path for the type.
$ scala
Welcome to Scala 2.12.0-M5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_92).
Type in expressions for evaluation. Or try :help.
scala> :pa
// Entering paste mode (ctrl-D to finish)
sealed abstract class Bar
case object BarOne extends Bar
case object BarTwo extends Bar
sealed abstract class Foo {
type A <: Bar
def f: A
}
object Foo {
object FooOne extends Foo {
type A = BarOne.type
val f = BarTwo
}
object FooTwo extends Foo {
type A = BarTwo.type
val f = BarOne
}
}
// Exiting paste mode, now interpreting.
<console>:26: error: overriding method f in class Foo of type => Foo.FooOne.A;
value f has incompatible type
val f = BarTwo
^
<console>:31: error: overriding method f in class Foo of type => Foo.FooTwo.A;
value f has incompatible type
val f = BarOne
^
The bug was this one, and the duplicate question is from last November.
The nature of the bug was also clever: it was introduced by -Yoverride-objects
, which is not a very useful option but figures in a couple of my S.O. answers, and now in a question.
Edit:
$ scala
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_92).
Type in expressions for evaluation. Or try :help.
scala> object X ; object Y
defined object X
defined object Y
scala> class C { def f: X.type = X }
defined class C
scala> class D extends C { override def f: Y.type = Y }
defined class D
scala> :quit
$ scalam
Welcome to Scala 2.12.0-M5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_92).
Type in expressions for evaluation. Or try :help.
scala> scala> object X ; object Y
// Detected repl transcript. Paste more, or ctrl-D to finish.
defined object X
defined object Y
scala> class C { def f: X.type = X }
defined class C
scala> class D extends C { override def f: Y.type = Y }
defined class D
// Replaying 3 commands from transcript.
scala> object X ; object Y
defined object X
defined object Y
scala> class C { def f: X.type = X }
defined class C
scala> class D extends C { override def f: Y.type = Y }
<console>:13: error: overriding method f in class C of type => X.type;
method f has incompatible type
class D extends C { override def f: Y.type = Y }
^
I dont't know what is going on here, but I did get the problem a bit more isolated. Also, it works with Foo subclasses as well as objects. I've confirmed this compiles on scalac 2.11.8:
object BarOne
object BarTwo
abstract class Foo[A] {
def attributeType: A
}
object FooContainer {
class FooOne extends Foo[BarOne.type] {
val attributeType = BarTwo
}
object FooTwo extends Foo[BarOne.type] {
val attributeType = BarOne
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With