加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala:指定默认的泛型类型,而不是Nothing

发布时间:2020-12-16 09:11:53 所属栏目:安全 来源:网络整理
导读:我有一对类似这样的课程.有一个Generator可以根据一些类级别的值生成一个值,一个GeneratorFactory构造一个Generator. case class Generator[T,S](a: T,b: T,c: T) { def generate(implicit bf: CanBuildFrom[S,T,S]): S = bf() += (a,b,c) result}case class
我有一对类似这样的课程.有一个Generator可以根据一些类级别的值生成一个值,一个GeneratorFactory构造一个Generator.

case class Generator[T,S](a: T,b: T,c: T) {
  def generate(implicit bf: CanBuildFrom[S,T,S]): S =
    bf() += (a,b,c) result
}

case class GeneratorFactory[T]() {
  def build[S <% Seq[T]](seq: S) = Generator[T,S](seq(0),seq(1),seq(2))
}

你会注意到GeneratorFactory.build接受一个类型为S的参数,Generator.generate产生一个S型的值,但是Generator没有存储类型S.

我们可以使用这样的类.工厂工作在一系列Char,并且生成一个String,因为build被赋予了一个String.

val gb = GeneratorFactory[Char]()
val g = gb.build("this string")
val o = g.generate

这是很好的,隐式地处理String类型,因为我们使用GeneratorFactory.

问题

现在,当我想要构建一个发电机而不经过工厂时,就会出现问题.我想能够做到这一点:

val g2 = Generator('a','b','c')
g2.generate // error

但是我得到一个错误,因为g2有类型Generator [Char,Nothing]和Scala“不能使用类型为Nothing的集合来构造一个类型为Not的类型为Not的集合.

我想要的是一种告诉Scala的方式,S的“默认值”类似于Seq [T]而不是Nothing.借用默认参数的语法,我们可以将其看作是:

case class Generator[T,S=Seq[T]]

解决方案不足

当然,如果我们明确地告诉生成器它的生成类型应该是什么,但是我认为一个默认选项会更好(我的实际场景更复杂):

val g3 = Generator[Char,String]('a','c')
val o3 = g3.generate  // works fine,o3 has type String

我想到了将Generator.apply重载为具有一个通用类型的版本,但这会导致错误,因为Scala无法区分两个应用定义:

object Generator {
  def apply[T](a: T,c: T) = new Generator[T,Seq[T]](a,c)
}

val g2 = Generator('a','c')  // error: ambiguous reference to overloaded definition

所需输出

我想要的方法是简单地构造一个Generator而不指定类型S,并将其默认为Seq [T],以便我可以做到:

val g2 = Generator('a','c')
val o2 = g2.generate
// o2 is of type Seq[Char]

我认为这将是用户最干净的界面.

有什么想法可以让这个发生吗?

解决方法

有没有理由你不想使用基本特征,然后根据需要在其子类中缩小S?以下例子符合您的要求:

import scala.collection.generic.CanBuildFrom

trait Generator[T] {
  type S
  def a: T; def b: T; def c: T
  def generate(implicit bf: CanBuildFrom[S,S]): S = bf() += (a,c) result
}

object Generator {
  def apply[T](x: T,y: T,z: T) = new Generator[T] {
    type S = Seq[T]
    val (a,c) = (x,y,z)
  }
}

case class GeneratorFactory[T]() {
  def build[U <% Seq[T]](seq: U) = new Generator[T] {
    type S = U
    val Seq(a,c,_*) = seq: Seq[T]
  }
}

我使S成为一种抽象类型,以便使用户不再需要它,但是您也可以将其设置为一个类型参数.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读