提供子类实例代替超类时的Scala错误?

发布于 2025-01-18 20:52:02 字数 1112 浏览 5 评论 0原文

我只是在Scala中尝试了一下,我写了此代码

object Main:
  def main(args: Array[String]): Unit =
    val dInt: Data[Int] = IntData(1)
    val dString: Data[String] = StringData("hello")
    val Data(deconstructedInt) = dInt // unapply
    val Data(deconstructedString) = dString // unapply
    println(deconstructedInt)
    println(deconstructedString)


sealed trait Data[+T]:
  def get: T

case class IntData(get: Int) extends Data[Int]

case class StringData(get: String) extends Data[String]

object Data:
  def apply[T](input: T): Data[T] = input match {
    case i: Int => IntData(i) //compile error here
    case s: String => StringData(s) //compile error here
  }

  def unapply[T](d: Data[T]): Option[String] = d match {
    case IntData(get) => Some(s"int data => get = $get")
    case StringData(get) => Some(s"string data => get = $get")
  }

,我在代码中评论的位置获得了此错误

Found:    IntData
Required: Data[T]
    case i: Int => IntData(i)

,为什么我会遇到此错误,不是intdata(或string> Stringdata )数据的子类

I am just trying things out in scala and I wrote this code

object Main:
  def main(args: Array[String]): Unit =
    val dInt: Data[Int] = IntData(1)
    val dString: Data[String] = StringData("hello")
    val Data(deconstructedInt) = dInt // unapply
    val Data(deconstructedString) = dString // unapply
    println(deconstructedInt)
    println(deconstructedString)


sealed trait Data[+T]:
  def get: T

case class IntData(get: Int) extends Data[Int]

case class StringData(get: String) extends Data[String]

object Data:
  def apply[T](input: T): Data[T] = input match {
    case i: Int => IntData(i) //compile error here
    case s: String => StringData(s) //compile error here
  }

  def unapply[T](d: Data[T]): Option[String] = d match {
    case IntData(get) => Some(s"int data => get = $get")
    case StringData(get) => Some(s"string data => get = $get")
  }

I get at the location commented in the code this error

Found:    IntData
Required: Data[T]
    case i: Int => IntData(i)

why I am getting this error, isn't IntData (or StringData) a subclass of Data ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

爱情眠于流年 2025-01-25 20:52:02

intdatadata [int]的子类型。因此,如果t不是intintdata 不是data [t]的子类型代码>。现在,您可能会说,如果输入与第一种情况匹配,则清楚地tint。但是编译器并不明智地意识到这一点!

您可以尝试使用Scala 3的新匹配类型:

type DataOf[T] = T match {
  case Int => IntData
  case String => StringData
}

def apply[T](input: T): DataOf[T] = input match {
  case i: Int => IntData(i)
  case s: String => StringData(s)
}

另一种选择是联合类型:

def apply(input: Int | String): Data[Int | String] = input match {
  case i: Int => IntData(i)
  case s: String => StringData(s)
}

但是,您将失去类型的信息。使用匹配类型解决方案,应用(42)被推断为具有类型intdata。使用联合类型解决方案,可以推断具有类型数据[int |字符串]

IntData is a subtype of Data[Int]. So if T is not Int, IntData is not a subtype of Data[T]. Now, you might say, if input matches the first case, then clearly T is Int. But the compiler is not smart to realise this!

You could try using Scala 3's new match types:

type DataOf[T] = T match {
  case Int => IntData
  case String => StringData
}

def apply[T](input: T): DataOf[T] = input match {
  case i: Int => IntData(i)
  case s: String => StringData(s)
}

Another alternative is union types:

def apply(input: Int | String): Data[Int | String] = input match {
  case i: Int => IntData(i)
  case s: String => StringData(s)
}

However, you will lose type information in doing this. Using the match types solution, apply(42) is inferred to have type IntData. Using the union types solution, it is inferred to have type Data[Int | String].

给妤﹃绝世温柔 2025-01-25 20:52:02

通过这种方式,编译器将 T 之间的点连接起来并且可以工作:

  object Main:
    def main(args: Array[String]): Unit =
      val dInt: Data[Int] = IntData(1)
      val dString: Data[String] = StringData("hello")
      val Data(deconstructedInt) = dInt // unapply
      val Data(deconstructedString) = dString // unapply
      println(deconstructedInt)
      println(deconstructedString)

  sealed trait Data[+T]:
    def get: T

  case class IntData[T <: Int](get: T) extends Data[T]

  case class StringData[T <: String](get: T) extends Data[T]

  object Data:
    def apply[T](input: T): Data[T] = input match {
      case i: Int    => IntData(i)
      case s: String => StringData(s)
    }

    def unapply[T](d: Data[T]): Option[String] = d match {
      case IntData(get)    => Some(s"int data => get = $get")
      case StringData(get) => Some(s"string data => get = $get")
    }

This way compiler connects the dots between Ts and it works:

  object Main:
    def main(args: Array[String]): Unit =
      val dInt: Data[Int] = IntData(1)
      val dString: Data[String] = StringData("hello")
      val Data(deconstructedInt) = dInt // unapply
      val Data(deconstructedString) = dString // unapply
      println(deconstructedInt)
      println(deconstructedString)

  sealed trait Data[+T]:
    def get: T

  case class IntData[T <: Int](get: T) extends Data[T]

  case class StringData[T <: String](get: T) extends Data[T]

  object Data:
    def apply[T](input: T): Data[T] = input match {
      case i: Int    => IntData(i)
      case s: String => StringData(s)
    }

    def unapply[T](d: Data[T]): Option[String] = d match {
      case IntData(get)    => Some(s"int data => get = $get")
      case StringData(get) => Some(s"string data => get = $get")
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文