2016-04-25 9 views
2

は、次のJavaコードでした:スカラ結合型パラメータと反射

public <T extends Enum<T>> T foo(Class<T> clazz) { 

    return clazz.getEnumConstants()[0]; 
} 

public void bar(Class<?> clazz) { 

    if (Enum.class.isAssignableFrom(clazz)) { 
     System.out.println(foo(clazz.asSubclass(Enum.class))); 
    } else if (String.class.isAssignableFrom(clazz)) { 
     System.out.println("Meow"); 
    } 
} 

bar(MyEnum.class) // prints the first value of MyEnum 
bar(String.class) // prints Meow 

はスカラに変換する:

bar[MyEnum]() 
bar[String]() 

EnumT extends Wrapper[T]パターンに従うクラスの一例であり、foo単にクラスの名前を返すだけでした(または、私の "Wrapper"クラスでのみ利用可能な反射データを必要とする他の種類のロジックを実行することもできます)。

TypeTagでScalaで動作させようとしましたが失敗しました。私はこのようなコンパイルエラーのすべての並べ替えを持って:すべてがコンパイル時に解決されるように、あなたは、型クラスのアプローチを試すことができます

答えて

3

は何実際必要はなく、行うには良い方法は非常に可能性があり、暗黙を見つける方法に興味があれば:

import language.existentials 
import reflect.ClassTag 

def foo[T <: Enum[T]](implicit ct: ClassTag[T]) = ct 

def bar[T](implicit ct: ClassTag[T]) = { 
    val clazz = ct.runtimeClass 

    if (classOf[Enum[_]].isAssignableFrom(clazz)) { 
    println(foo(ct.asInstanceOf[ClassTag[A] forSome { type A <: Enum[A] }])) 
    } else { 
    println("not a enum") 
    } 
} 
+0

私はちょうど "リテラル翻訳"で私の答えを編集していたが、それを投稿したので、私はあなたにそれを残すだろう:実在のタイプの+1、おそらくそれは彼が知りたかったものだ –

+0

はい!同様のことを試しましたが、 'asInstanceOf'には単純な' Class [_ <:Enum [_]] '(実際には' Class'を必要とするJavaメソッドが呼び出されています)がありましたが、 (ここで説明されているように(http://www.drmaciver.com/2008/03/existential-types-in-scala))、私はそれを修正するのが面倒です:p –

1

inferred type arguments [?0] do not conform to method foo's type parameter bounds [E <: Enum[E]]、反射が関与していない:

import scala.reflect.ClassTag 

trait DoSomething[T] { 
    def apply(): Unit 
} 

object DoSomething { 
    implicit def enumDoSomething[E <: Enum[E]](implicit ct: ClassTag[E]) = new DoSomething[E] { 
    def apply() = println(ct.runtimeClass.getEnumConstants()(0)) 
    } 

    implicit object stringDoSomething extends DoSomething[String] { 
    def apply() = println("Meow") 
    } 
} 

object Test extends App { 
    def foo[A](implicit doSomething: DoSomething[A]) = doSomething() 

    foo[java.util.concurrent.TimeUnit] 
    foo[String] 
} 

あなたが「ドンこうif-elseを持っていて、あなたはより良い懸念を持っています。

"デフォルト"の場合、キャッチオール暗黙にすることができます。

import scala.reflect.ClassTag 

trait DoSomething[T] { 
    def apply(): Unit 
} 

object DoSomething { 

    implicit def enumDoSomething[E <: Enum[E]](implicit ct: ClassTag[E]) = new DoSomething[E] { 
    def apply() = println(ct.runtimeClass.getEnumConstants()(0)) 
    } 

    implicit object stringDoSomething extends DoSomething[String] { 
    def apply() = println("Meow") 
    } 

    implicit def catchAll[T] = new DoSomething[T] { 
    def apply() = { 
     println("test") // some default case 
    } 
    } 
} 

object Test extends App { 
    def foo[A](implicit doSomething: DoSomething[A]) = doSomething() 

    foo[java.util.concurrent.TimeUnit] // prints NANOSECONDS 
    foo[String] // prints Meow 
    foo[Long] // prints test 
} 

あなたはScalaはtake a look at this

+0

はい、これは可能ですが、私が求めたものではありません。私はおそらく十分ではなかったでしょう。 'bar'型のパラメータは束縛されてはいけません(単に' A')、 'foo'を使用しなければなりません。さらに、 'bar'メソッドは' String'でコンパイルされません(私の例のように)。 –

+0

ああ、今私は何かを試してみましょう –

+0

1)それは私のためにコンパイルされません。あなたはそれを試しましたか? 2)私は 'foo'をそれほど変更しないで(私の' foo' =あなたの 'enumDoSomething')それを行う方法を探しています。 –

関連する問題