6

我有两个案例类

case class StringCaseClass(argument: String)

case class IntCaseClass(argument: Int)

我想定义一个结构类型,它将匹配这两者的伴随对象

type HasApply1 {
  def apply[A, R](argument: A): R
}

这会编译得很好,但是当我尝试像这样使用它时

def method(caseClass: HasApply1) {
  // whatever
}

method(StringCaseClass)

我会得到一个编译器错误

found   : StringCaseClass.type
required: WithApply1
            (which expands to)  AnyRef{def apply[A, R](string: A): R}

有没有办法做到这一点?如果我将结构类型重新定义为具有 A 和 R 的具体类型,它将正确编译,但是我失去了灵活性

4

3 回答 3

9

@aloiscochard 的评论几乎就在那里。他忘记提到的是案例类伴生对象已经实现了适当的FunctionN特征,所以你可以简单地这样做,

scala> case class StringCaseClass(argument: String)
defined class StringCaseClass

scala> case class IntCaseClass(argument: Int)
defined class IntCaseClass

scala> def method[A, R](caseClass: A => R, a: A) = caseClass(a)
method: [A, R](caseClass: A => R, a: A)R

scala> method(StringCaseClass, "foo")
res0: StringCaseClass = StringCaseClass(foo)

scala> method(IntCaseClass, 23)
res1: IntCaseClass = IntCaseClass(23)
于 2013-03-24T18:55:53.267 回答
3

一般来说,您应该避免结构类型,因为它非常昂贵。由于 JVM 的限制,该调用将转换为反射调用。当您开始使用 scala 2.10 结构类型时,将在编译时产生警告(尽管您可以使用标志禁用它)。

如果您正在寻找一种更通用的方法来向不共享继承层次结构的类添加功能,您可以使用类型类。

这是一个简单的例子:

trait CanCreateRFromA[A,R]{
    def createNew(a:A): R
}

implicit object CanCreateBlahFromInt extends CanCreateRFromA[Int,Blah2]{
    def createNew(i:Int):Blah2 = new Blah2(i)
}


implicit object CanCreateBlah1FromString extends CanCreateRFromA[String,Blah1]{
    def createNew(s:String):Blah1 = new Blah1(s)
}

case class Blah1(something:String)
case class Blah2(something:Int)

def createRFromA[A,R](a:A)(implicit tc:CanCreateRFromA[A,R])= tc.createNew(a)

然后你可以调用:

createRFromA(1) // This gives a Blah2
createRFromA("1") // This gives a Blah1

同样,我不确定您要完成什么,但是使用类型类可能会做您想做的事情,而且速度会快得多。

于 2013-03-24T14:07:12.437 回答
0

您没有将 的实例传递StringCaseClass给您的method. 你在那里传递的是伴随对象StringCaseClass(它是为案例类自动生成的)。

试试这是否有效:method(StringCaseClass("dummy")).

于 2013-03-24T13:52:31.433 回答