使用结构类型时出现意外错误

Getting unexpected error when using structure type

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

val a = "abc".toCharArray

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

A(a)

但它给出了以下错误:

Error:(3, 16) AnyRef{def mkString(): String} does not take type parameters case class A[T: {def mkString(): String}](i: T)

Error:(4, 14) value mkString is not a member of type parameter T val s = i.mkString

我正在使用 Scala 2.11.6。

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

类型边界 [A : B] 是一种 shorthand 表示存在类型 class B 类型 A 实例的方式,所以这些等价于:

def foo[A : B]: C

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

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

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

This member is added by an implicit conversion from Array[T] to ArrayOps[T] performed by method genericArrayOps in scala.Predef.

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

val a = "abc".toCharArray

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

A(a)

至少有三个错误:

  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])