【问题标题】:Getting unexpected error when using structure type使用结构类型时出现意外错误
【发布时间】:2018-12-29 02:48:52
【问题描述】:

我是 Scala 编程的新手,所以如果这是一个愚蠢的问题,请多多包涵。我期待下面的代码可以工作,因为a 有一个mkString 方法。

val a = "abc".toCharArray

case class A[T: {def mkString(): String}](i: T) {
  val s = i.mkString
}

A(a)

但它给出了以下错误:

错误:(3, 16) AnyRef{def mkString(): String} 不接受类型 参数 case class A[T: {def mkString(): String}](i: T)

错误:(4, 14) 值 mkString 不是类型参数 T val 的成员 s = i.mkString

我使用的是 Scala 2.11.6。

任何帮助将不胜感激!谢谢!

【问题讨论】:

    标签: arrays scala types structural-typing


    【解决方案1】:

    类型边界[A : B] 是一种简写方式,表示存在类型B 的类型类A 的实例,因此它们是等价的:

    def foo[A : B]: C
    
    def foo[A](implicit b: B[A]): C
    

    您可能正在寻找的语法是[A <: B],这意味着A 必须是B 的子类。

    但是你会遇到mkString 实际上不在Array 类中的问题;如文档中所述,它在ArrayOps 中定义(从Array 隐式转换):

    这个成员是通过从 Array[T] 到 ArrayOps[T] 由 scala.Predef 中的 genericArrayOps 方法执行。

    您可以通过以下方式解决这个问题:

    val a = "abc".toCharArray
    
    case class A[T](i: T)(implicit conv: T => {def mkString: String}) {
      val s = conv(i).mkString
    }
    
    A(a)
    

    【讨论】:

      【解决方案2】:

      至少有三个错误:

      1. 应该是<:,而不是:。结构类型不是类型类。
      2. def mkString(): Stringdef mkString: String 不同。
      3. 原始 JVM 数组对诸如 mkString 之类的便捷 scala 方法一无所知。为此,您需要 WrappedArray

      这里可行:

      import scala.language.reflectiveCalls
      val a = "abc".toCharArray
      
      import collection.mutable.WrappedArray
      
      case class A[T <: { def mkString: String }](i: T){
        val s = i.mkString
      }
      
      A(a: WrappedArray[Char])
      

      【讨论】:

      • 谢谢安德烈!只是一个简单的问题,import scala.language.reflectiveCalls 的目的是什么?
      • @BubbleBubbleBubbleGut 防止编译器向我抛出警告并建议导入 `scala.language.reflectiveCalls' ;)
      • 哦,明白了!谢谢!!
      • 嘿安德鲁,如果你有时间,你能看看我刚刚发布的另一个问题吗?真的很感激你也可以帮助我
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-14
      • 1970-01-01
      • 1970-01-01
      • 2011-11-09
      • 2017-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多