【问题标题】:Access abstract type member from outside从外部访问抽象类型成员
【发布时间】:2016-02-22 04:07:08
【问题描述】:

当使用抽象类型成员时,如果不使用 asInstanceOf,我就无法从外部使用该类型,还有其他选择吗?为什么抽象类型不让自己被“覆盖”以便知道它是 Int 还是 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

【问题讨论】:

    标签: scala


    【解决方案1】:

    编译器在检查y 时不会查看s 的定义,只会查看其类型。所以它只知道s.head是一个Param,而它的A是抽象的。要让编译器知道s.head.get 是Int,它必须知道s.head 是IParam。

    或者你可以这样看:如果这个类型被检查,那么你可以将s的定义更改为val s = Set[Param](SParam("s"))而不更改任何类型。但是很明显y: Int 不应该进行类型检查。

    【讨论】:

      【解决方案2】:

      使用类型别名的全部意义在于封装来自外部世界的具体类型。这为您提供了实现类型的抽象。因此,如果您想将IParam 的类型更改为Double,则不必在整个代码库中更改类型。

      您可以在get 的函数签名中看到它返回类型A 而不是Int

      def get : A = x

      我认为您想要的功能可以通过以下方式实现:

      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
      

      【讨论】:

        猜你喜欢
        • 2018-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-13
        • 2013-10-21
        相关资源
        最近更新 更多