gpt4 book ai didi

scala - 在运行时检查 Scala 类型和类型删除

转载 作者:行者123 更新时间:2023-12-01 12:20:55 25 4
gpt4 key购买 nike

假设我们有几个这样的类:

abstract class Throw {
def winsOver(t2: Throw): Boolean
}

class Rock extends Throw {
override def winsOver(t2: Throw): Boolean = t2 match {
case _: Scissors => true
case _ => false
}
}

class Scissors extends Throw {
override def winsOver(t2: Throw): Boolean = t2 match {
case _: Paper => true
case _ => false
}
}

class Paper extends Throw {
override def winsOver(t2: Throw): Boolean = t2 match {
case _: Rock => true
case _ => false
}
}

这行得通

scala>new Paper winsOver new Rock
res0: Boolean = true
scala>new Rock winsOver new Rock
res1: Boolean = false

但是,代码有很多重复。由于唯一不同的是他们击败的类型,我们可以尝试将其排除在外

abstract class Throw {

type Beats <: Throw

def winsOver(t2: Throw): Boolean = t2 match {
case _: Beats => true
case _ => false
}

}

class Rock {
type Beats = Scissors
}

class Scissors {
type Beats = Paper
}

class Paper {
type Beats = Rock
}

但是编译器开始报错

warning: abstract type pattern Throw.this.Beats is unchecked since it is eliminated by erasure
case _: Beats => true

果然,它不起作用。 winsOver 突然总是返回 true

scala>new Rock winsOver new Rock
res0: Boolean = true

我一直在努力解决这个问题,根据我的发现,这是因为 JVM 没有尽可能多地携带类型信息。这会导致一些信息丢失(“删除”),并且有一些方法可以在 Scala 中解决这个问题,以前使用 list ,现在使用类标签和类型标签。

我还没有真正能够更具体地弄清楚这是如何工作的,虽然有时我能够从互联网上复制代码片段来做类似的事情,但我真的不明白这些代码是如何工作的,而且我不能适应这个例子。我还注意到有一个 shapeless 库对这种东西有很多支持,但我也想了解它是如何工作的。

最佳答案

你不应该在运行时检查类型信息。 Type erasure is a good thing Scala 应该删除比它更多的类型。

相反,使用代数数据类型和模式匹配:

sealed abstract class Throw {
def winsOver(t2: Throw): Boolean
}

case object Rock extends Throw {
def winsOver(t2: Throw): Boolean = t2 match {
case Scissors => true
case _ => false
}
}

case object Scissors extends Throw {
def winsOver(t2: Throw): Boolean = t2 match {
case Paper => true
case _ => false
}
}

case object Paper extends Throw {
def winsOver(t2: Throw): Boolean = t2 match {
case Rock => true
case _ => false
}
}

这有一些重复,所以我们可以把它分解出来:

sealed abstract class Throw {
def winsOver(t2: Throw): Boolean = (this,t2) match {
case (Paper, Rock) | (Rock, Scissors) | (Scissors,Paper) => true
case _ => false
}
}

case object Rock extends Throw
case object Scissors extends Throw
case object Paper extends Throw

这按预期工作:

scala> Rock winsOver Scissors
res0: Boolean = true

scala> Paper winsOver Scissors
res1: Boolean = false

关于scala - 在运行时检查 Scala 类型和类型删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44023023/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com