6

2つのケースクラスがあります

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 に答える