When using an abstract type member I can't use the type from outside without using asInstanceOf, is there any other choice? Why doesn't the abstract type let itself be "overriden" so it know it's an Int or a String?
scala> trait Param { type A
| val x:A
| def get:A = x
| }
scala> case class IParam(override val x:Int) extends Param {type A = Int}
defined class IParam
scala> case class SParam(override val x:String) extends Param {type A = String}
defined class SParam
scala> val s = Set[Param](IParam(1), SParam("s"))
s: scala.collection.immutable.Set[Param] = Set(IParam(1), SParam(s))
scala> val y:Int = s.head.get
<console>:26: error: type mismatch;
found : Param#A
required: Int
val y:Int = s.head.get
The compiler isn't going to be looking at the definition of s
while type-checking y
, only at its type. So it only knows that s.head
is a Param
, and its A
is abstract. To let the compiler tell that s.head.get
is Int
, it must know s.head
is IParam
.
Or you can see it like this: if this type-checked, then you could change definition of s
to val s = Set[Param](SParam("s"))
without changing any types. But then it's clear that y: Int
shouldn't type-check.
The whole point of using type aliases is to encapsulate the concrete type from the outside world. This gives you an abstraction of what the implementation type is. Therefore if you wanted to change the type of IParam
to a Double
, you wouldn't have to change the type throughout your entire code base.
You can see in the function signature of get
that it returns a type A
NOT an Int
def get : A = x
I think the functionality you desire could be achieved the following way:
scala> trait Param[T] { val x : T; def get : T = x }
defined trait Param
scala> val s = IParam(1)
s: IParam = IParam(1)
scala> val y : Int = s.get
y: Int = 1
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.