2013-03-24 9 views
6

私はこれは罰金コンパイルされますが、私はそれを使用しようとすると、これらのジェネリックパラメータで構造タイプを使用するにはどうすればよいですか?

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

の両方のコンパニオンオブジェクトに一致する構造型を定義したい2ケースクラス

case class StringCaseClass(argument: String) 

case class IntCaseClass(argument: Int) 

を持っていますこの

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の具体的な型を持つように構造型を再定義すると、正しくコンパイルされますが、柔軟性が失われます

+0

これを行うことができますので、私はこのようなメソッドを作成したいと考え、適切なFunctionN形質を実装すでにオブジェクトされますメソッドA [A](caseClass:HasApply1、a:A)= caseClass.apply(a) ' – shinyhappydan

答えて

9

@ aloiscochardのコメントはほぼあります。 `DEF:何彼は言及を忘れてしまったと、そのケースクラスの仲間は、あなたは、単に、さらに明確にするため

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) 
+0

これは私が必要とするものです。私はあなたがそれをすることができないということを質問したときの質問に対する本当の答えを考えています。しかし、これは私のために働きます。 – shinyhappydan

+0

ワウ・マイルズ、それは素晴らしいです。私は昨日それに戻ってくる機会がありませんでしたが、それは私が思いついたよりも優れています! +1! – coltfred

0

methodにインスタンスStringCaseClassを渡しませんでした。あなたが渡したものは、StringCaseClassのコンパニオンオブジェクトです(これはケースクラス用に自動的に生成されます)。

この場合、試してください:method(StringCaseClass("dummy"))

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 

再び私はあなたが達成しようとしているかわからないんだけど、おそらく何を行うことが可能ですあなたは型クラスを使いたいと思うし、もっと速くなるだろう。

+2

軽量の代替案は、作成する代わりにタイプ' Function1 [A、R] '(または' A => R') CanCreateRFrom形質。 –

+0

@coltfred私が何をしようとしているのかをさらに明確にするために、元の投稿に私のコメントを見てください。私は操作の費用について気にしない – shinyhappydan

関連する問題