如何返回通配符泛型

如何返回通配符泛型

本文介绍了如何返回通配符泛型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带参数的类型别名,我想从一个方法返回不同参数类型的实例:

I have a type alias with parameter and I would like to return the instance of different parameter types from a method:

type TC[T] = (ClassTag[T], Option[T])

def gen(x: Int): TC[_] = x match {
  case 0 => (classTag[Int], Option[Int](0))
  case _ => (classTag[String], Option[String](""))
}

这不起作用,并给我错误:

This does not work and gives me error:

我尝试使用Any代替通配符_,但仍然无法正常工作:

And I tried to use Any instead of wildcard _, and it still does not work:

def gen(x: Int): TC[Any]

如何实现?

推荐答案

最好返回特定类型,而不是存在类型.如果要gen根据其参数返回不同的类型,则实际上gen是多态函数.使用类型类和单例类型尝试以下方法.

It's better to return specific type rather than existential. If you want gen to return different types depending on its argument then actually gen is a polymorphic function. Try the following approach with type class and singleton types.

type TC[T] = (ClassTag[T], Option[T])

trait Gen[X <: Int] {
  type Out
  def apply(x: X): Out
}
trait LowPriorityGen {
  type Aux[X <: Int, Out0] = Gen[X] { type Out = Out0 }
  def instance[X <: Int, Out0](f: X => Out0): Aux[X, Out0] = new Gen[X] {
    override type Out = Out0
    override def apply(x: X): Out0 = f(x)
  }

  implicit def default[X <: Int : ValueOf]: Aux[X, TC[String]] = instance(_ => (classTag[String], Option[String]("")))
}
object Gen extends LowPriorityGen {
  implicit val zero: Aux[0, TC[Int]] = instance(_ => (classTag[Int], Option[Int](0)))
}

def gen[X <: Int with Singleton](x: X)(implicit g: Gen[X]): g.Out = g(x)

gen(0) //(Int,Some(0))
gen(1) //(java.lang.String,Some())


原因类似于中的原因.上一个问题. ClassTagOption的方差不同.


Reasons are similar to those in the previous question. ClassTag and Option have different variance.

尝试

type TC[T] = (ClassTag[_ <: T], Option[T])

def gen(x: Int): TC[_] = x match {
  case 0 => (classTag[Int], Option[Int](0))
  case _ => (classTag[String], Option[String](""))
}


即使您不能在类型中编码所需的属性,您仍然可以在编译时使用模式匹配右侧的check对其进行检查.


Even if you can't encode desirable property in types you still can check it at compile time with check in right hand side of pattern matching.

def gen(x: Int): (ClassTag[_], Option[_]) = x match {
  case 0 => check(classTag[Int], Option[Int](0))
  case _ => check(classTag[String], Option[String](""))
}

def check[T](classTag: ClassTag[T], option: Option[T]): (ClassTag[T], Option[T]) = (classTag, option)

这篇关于如何返回通配符泛型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-25 04:34