簡體   English   中英

Scala綁定類型參數和反射

[英]Scala bound type parameter and reflection

可以使用以下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

被翻譯成Scala:

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

Enum只是遵循T extends Wrapper[T]模式的類的示例,而foo可以簡單地返回該類的名稱(或執行任何其他類型的邏輯,這些邏輯需要僅在我的“ Wrapper ”中可用的反射數據”)。

我試圖通過TypeTag使它在Scala中工作,但是失敗了。 我遇到了各種各樣的編譯錯誤,例如: inferred type arguments [?0] do not conform to method foo's type parameter bounds [E <: Enum[E]]

很有可能有一種更好的方法可以滿足您的實際需求,但是:

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")
  }
}

您可以嘗試使用類型類方法,以便在編譯時解決所有問題,而無需進行反射:

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如何找到隱式內容感興趣, 請看一下

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM