2012-04-15 5 views
1

抽象クラスでありクラスクラスを持つクラスAを想像してみてください。私たちは、セットクラスがいくつあるのか、それらのケースクラスの名前さえ知っていません。スカラでパターンマッチングで使用するための未知のcaseクラスを引数として受け入れるメソッドを宣言する

abstract class A(field: String) 
//Example of a case class that extends A 
case class B(f: String) extends A(f) 

は今、私はこれがあります。

a match { 
    case B(f) => println("f") 
} 

をそして私はメソッドに引数によってケースクラスの種類を渡したいです。私がこれをしたいのは、ファイルに一連のルールを設定するからです。そして、私はそれらのルールをロードし、それらのルールが提供するいくつかの情報とパターンマッチングを使用したいと思います。私はこのようなことをしたい:

def printer (a: A, B: A) = { 
    a match{ 
     case B(f) => println("f") 
    } 
} 

これは可能ですか?

それほど簡単ではない場合は、パターンマッチングで抽象クラスを使用できますか?すべてのケースクラスの主要な構造を持っているので、抽象クラスを単純に使うことができれば完璧です。

はEDIT:

は、クラスAに基づいて何かを使用するのが良いでしょうので、異なる引数を持つことができ、その場合のクラスを言及するのを忘れた

+0

を書くことができます[あなたが達成しようとして*あなたが本当に*ているものについての詳細を説明する場合は、おそらくより建設的な答えを得るでしょう。](http://homepage.ntlworld.com/jonathan。 deboynepollard/FGA/put-down-the-chocolate-covered-banana.html) –

+0

私はあなたに同意しますが、もしそうすれば、これは一種の巨大な投稿になるでしょう。このように、私は必要なものに集中します。 –

答えて

5

ない(私は唯一のフィールドとのマッチング私のパターンを行うことができますので)あなたはそれを試したように。しかし、あなたがバインドコンテキストとしてマニフェストを使用している場合、あなたはそれを動作させることができます。

scala> trait Foo 
defined trait Foo 

scala> case class Bar(baz: String) extends Foo 
defined class Bar 

scala> def boo[A <: Foo : Manifest](foo: Foo) = 
    | if (foo.getClass isAssignableFrom manifest[A].erasure) "foo" else "boo" 
boo: [A <: Foo](foo: Foo)(implicit evidence$1: Manifest[A])java.lang.String 

scala> boo[Foo](Bar("")) 
res0: java.lang.String = boo 

scala> boo[Bar](Bar("")) 
res1: java.lang.String = foo 
+0

"コンテキストバインドとしてのマニフェスト"。それは何を意味するのだろうか?どちらにせよ、私はパターンマッチングでそれを使うことはできません... –

1

あなたはあなたのケースクラスのコンパニオンオブジェクトからunapply方法を抽出し、それを使用することができます。

scala> :paste 
// Entering paste mode (ctrl-D to finish) 

abstract class A(field: String) 
case class B(f: String) extends A(f) 
case class C(f: String) extends A(f) 
case class E(f: String, f1: Int) extends A(f) 
case class F(f: String, f1: Int) extends A(f) 

class Unapplyer[T: Manifest, R](f: T => Option[R]) { 
    def unapply(a: Any): Option[R] = { 
    if (manifest[T].erasure.isInstance(a)) f(a.asInstanceOf[T]) else None 
    } 
} 

def printer[T: Manifest, R](a: A, b: T => Option[R]) { 
    val P = new Unapplyer(b) 
    a match { 
    case P((f, f1)) => println(f + " - " + f1) 
    case P(f) => println(f) 
    case _ => println("oops") 
    } 
} 

// Exiting paste mode, now interpreting. 

defined class A 
defined class B 
defined class C 
defined class E 
defined class F 
defined class Unapplyer 
printer: [T, R](a: A, b: (T) => Option[R])(implicit evidence$2: Manifest[T])Unit 

scala> printer(B("test"), B.unapply _) 
test 

scala> printer(B("test"), C.unapply _) 
oops 

scala> printer(E("test", 1), E.unapply _) 
test - 1 

scala> printer(E("test", 1), F.unapply _) 
oops 

scala> printer(E("test", 1), B.unapply _) 
oops 

UPD:可変数と種類の引数を追加して使用しました。

+0

クラスで何をしているのか分かりませんでしたが、私は事例クラスにはさまざまな引数があることを忘れていました。そして、あなたのソリューションでは、それは非常に議論に依存しているようですね? –

+0

@TiagoAlmeida: 'unapply'メソッドが' TupleN'を返すので、任意の数の引数を持つケースクラスを使用できます。私は私の答えを更新しました。 – senia

+0

@TiagoAlmeida:クラス 'Unapplyer'は何らかの"手動パターンマッチング "を実装しています。 'unapply'メソッドは引数の型をチェックします:適合すれば内側の 'unapply'関数が使用されます。そうでなければ一致は失敗します。 – senia

0

なぜ型をメソッドに渡すのかわかりません。パターンマッチングを使用すると、とにかくタイプをチェックします。ではなぜそれを渡すのですか? あなただけ

abstract class A(field: String) 
case class B(f: String) extends A(f) 
case class C(i: Int) extends A(i.toString) 

def printer (a: A) = { 
    a match{ 
     case B(f) => println(f) 
     case C(i) => println(i) 
    } 
} 
+0

問題は、どのケースクラスを一致させたいのか分かりません。パターンマッチングをファイルからロードするとします。どのようなケースクラスを使用するかを受け入れるメソッドをどのように開発できますか? –

関連する問題