【问题标题】:Generic type in ScalaScala 中的泛型类型
【发布时间】:2020-09-10 09:41:09
【问题描述】:

我最近开始学习 Scala。而且我不明白为什么这段代码不起作用。有人可以帮帮我吗?

import scala.collection.mutable
import scala.collection.mutable.Map

class Bijection[T] (val v: Set[T]) {
  private var addition = 0
  private var reversed = false

  def add(i: Int)(implicit ev: T <:< Int) = {
    addition += i
  }

  def reverse(implicit ev: T <:< String) = {
    reversed = !reversed
  }
}

object Bijection {
  def apply(s: Set[String]): Bijection[String] = {
    println("Hello string")
    Bijection(s)
  }

  def apply[T](s: Set[T]): Bijection[T] = {
    println("Hello T")
    Bijection(s)
  }
}

object Main {
  def main(args: Array[String]): Unit = {
    var x = Bijection[String](Set[String]("fd", "fasf"))
  }
}

此代码应打印“Hello” 但我现在得到下一个踪迹。

Error:(23, 7) double definition:
def apply(s: Set[String]): Bijection[String] at line 18 and
def apply[T](s: Set[T]): Bijection[T] at line 23
have same type after erasure: (s: scala.collection.immutable.Set)Bijection
  def apply[T](s: Set[T]): Bijection[T] = {

【问题讨论】:

  • 使用new不会调用main中的apply方法。正如上面的评论所提到的,您需要删除新的 keyward 才能调用 Bijection.apply。 (你不需要 [String] 类型参数)最后你还需要显式或隐式地提供预期的参数忽略
  • @user 你是天才!非常感谢您提出这个问题和以前的问题。
  • 我更新问题@user 你能看到吗?
  • 你不能在你的apply方法中只使用Bijection(s),因为这会再次调用apply方法,导致递归。相反,在那里调用实际的构造函数,并将您的主构造函数设为私有。
  • 是,但错误现在不在递归中。

标签: java scala abstract-class generic-programming


【解决方案1】:

JVM 没有reified generics,而是在运行时有erases type parameters,即使它们存储在字节码中。它具有类型参数的唯一原因是在编译时进行检查。因此,您的 2 个应用方法都将具有签名。

def apply(s: Set): Bijection

在运行时。

因此,无法选择正确的应用方法。

此外,您必须在 apply 方法中调用构造函数。如果你不使用new,那么你将再次调用相同的apply方法,进入无限递归。

相反,您可以这样做。如果不是字符串,则隐式参数将保持为空,您将知道它不是String,而是其他一些T

object Bijection {
  private def applyString(s: Set[String]): Bijection[String] = {
    println("Hello String")
    new Bijection(s)
  }
  
  private def applyT[T](s: Set[T]): Bijection[T] = {
    println("Hello T")
    new Bijection(s)
  }
  
  def apply[T](s: Set[T])(implicit ev: Set[T] =:= Set[String] = null): Bijection[T] =
    if (ev == null) applyT(s) else applyString(s).asInstanceOf[Bijection[T]]
}

您无需更改任何其他内容。

Scastie

【讨论】:

  • 你试过其他类型的吗? Int 的示例不起作用。
  • @archi1998 你再试一次吗?它现在应该可以工作了。我忘记将 ev 默认设置为 null
猜你喜欢
  • 2012-11-29
  • 1970-01-01
  • 2015-07-09
  • 2020-03-27
  • 2012-11-16
  • 1970-01-01
  • 2013-12-21
  • 1970-01-01
相关资源
最近更新 更多