Array map()期间令人费解的隐式转换

时间:2014-08-01 03:17:44

标签: java arrays scala implicit-conversion implicit

我有一个用例,我给了一个包装类的Java数组,例如,包装一个int,我想将它们转换为相同数据的ValueSet,但是我遇到了隐含转换的一个令人费解的问题。这是我尝试做的Java和Scala的一个例子:

... /爪哇/ demoapi / SomeWrapper.java

package demoapi;

public class SomeWrapper {
    public static final int JavaOne = 1;
    public static final int JavaTwo = 2;
    public int m_theInt;
};

... /阶/ demo.scala

package demotest

import demoapi._

object TestEnum extends Enumeration {
  val One, Two = Value
}

object SomeWrapperEx {
  implicit def fromJava(in: Array[SomeWrapper]): TestEnum.ValueSet = {
    in.map(x => fromInt(x.m_theInt))
  }
  def fromInt(in: Int): TestEnum.Value = {
    in match {
      case SomeWrapper.JavaOne => TestEnum.One
      case SomeWrapper.JavaTwo => TestEnum.Two
    }
  }
}

地图无法编译,出现以下错误:

Error:(11, 27) value m_theInt is not a member of demotest.TestEnum.Value
    in.map(x => fromInt(x.m_theInt))
                          ^

我的问题是:数组元素的类型如何转换为TestEnum.Value?我不得不通过放弃这些隐含的方式来解决这些问题,但我觉得这应该以某种方式起作用......

编辑:我确信我需要做的更多才能让它工作,例如可能将Array [TestEnum.Value]转换为ValueSet,但我还没有达到这一点。

1 个答案:

答案 0 :(得分:1)

您希望将Array转换为集合(ArrayOps),以便对其进行操作。

但是你期望生成一个ValueSet,为此,机器需要一种方法来构建它,一个CanBuildFrom。

这里隐含地提供了这个:

See the docs for ValueSet

由于您提供了一种将Array转换为ValueSet的方法,因此很乐意应用它来使用可用的CanBuildFrom。

-Xprint:typer向您展示了它的方向:

implicit def fromJava(in: Array[demoapi.SomeWrapper]): demoapi.TestEnum.ValueSet = SomeWrapperEx.this.fromJava(in).map[Nothing, demoapi.TestEnum.ValueSet](((x: demoapi.TestEnum.Value) => SomeWrapperEx.this.fromInt(x.<m_theInt: error>)))(demoapi.this.TestEnum.ValueSet.canBuildFrom);

我在使用ValueSet作为普通集合时遇到了问题,所以现在我没有。

例如,始终以ValueSet开头:

$ scala
Welcome to Scala version 2.11.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_05).
Type in expressions to have them evaluated.
Type :help for more information.

scala> object Days extends Enumeration { val M,T,W,Th,F,Sa,S = Value }
defined object Days

scala> val ds = (2 to 5).toArray
ds: Array[Int] = Array(2, 3, 4, 5)

scala> Days.values filter (ds contains _.id)
res0: Days.ValueSet = Days.ValueSet(W, Th, F, Sa)

或手工构建:

scala> Days.ValueSet.empty
res1: Days.ValueSet = Days.ValueSet()

scala> res1 + Days.T
res2: Days.ValueSet = Days.ValueSet(T)

无论如何都是CanBuildFrom:

scala> implicit val xxx = new collection.generic.CanBuildFrom[Array[Int], Days.Value, Days.ValueSet] {
     | def apply() = Days.ValueSet.newBuilder
     | def apply(from: Array[Int]) = apply()
     | }
xxx: scala.collection.generic.CanBuildFrom[Array[Int],Days.Value,Days.ValueSet] = $anon$1@6b474074

scala> (2 to 5) map (_ => Days.T)
res4: scala.collection.immutable.IndexedSeq[Days.Value] = Vector(T, T, T, T)

scala> (2 to 5) map (Days(_))
res5: scala.collection.immutable.IndexedSeq[Days.Value] = Vector(W, Th, F, Sa)