gpt4 book ai didi

scala - 如何避免在 Scala 中调用 asInstanceOf

转载 作者:行者123 更新时间:2023-12-03 14:06:47 31 4
gpt4 key购买 nike

这是我的代码的简化版本。
如何避免调用asInstanceOf (因为这是一个糟糕的设计解决方案的气味)?

sealed trait Location
final case class Single(bucket: String) extends Location
final case class Multi(buckets: Seq[String]) extends Location

@SuppressWarnings(Array("org.wartremover.warts.AsInstanceOf"))
class Log[L <: Location](location: L, path: String) { // I prefer composition over inheritance
// I don't want to pass location to this method because it's a property of the object
// It's a separated function because there is another caller
private def getSinglePath()(implicit ev: L <:< Single): String = s"fs://${location.bucket}/$path"

def getPaths(): Seq[String] =
location match {
case _: Single => Seq(this.asInstanceOf[Log[_ <: Single]].getSinglePath())
case m: Multi => m.buckets.map(bucket => s"fs://${bucket}/$path")
}
}

最佳答案

尝试类型类

class Log[L <: Location](location: L, val path: String) {
def getSinglePath()(implicit ev: L <:< Single): String = s"fs://${location.bucket}/$path"
def getPaths()(implicit gp: GetPaths[L]): Seq[String] = gp.getPaths(location, this)
}

trait GetPaths[L <: Location] {
def getPaths(location: L, log: Log[L]): Seq[String]
}
object GetPaths {
implicit val single: GetPaths[Single] = (_, log) => Seq(log.getSinglePath())
implicit val multi: GetPaths[Multi] = (m, log) => m.buckets.map(bucket => s"fs://${bucket}/${log.path}")
}
通常,类型类是模式匹配的编译时替换。
我必须制作 getSinglePath公开和 path一个 val为了在 GetPaths 内提供对它们的访问权限.如果您不想这样做,您可以将类型类嵌套到 Log
class Log[L <: Location](location: L, path: String) {
private def getSinglePath()(implicit ev: L <:< Single): String = s"fs://${location.bucket}/$path"
def getPaths()(implicit gp: GetPaths[L]): Seq[String] = gp.getPaths(location)

private trait GetPaths[L1 <: Location] {
def getPaths(location: L1): Seq[String]
}
private object GetPaths {
implicit def single(implicit ev: L <:< Single): GetPaths[L] = _ => Seq(getSinglePath())
implicit val multi: GetPaths[Multi] = _.buckets.map(bucket => s"fs://${bucket}/$path")
}
}

实际上我们不必通过 location明确的,我们不需要 L1
class Log[L <: Location](location: L, path: String) {
private def getSinglePath()(implicit ev: L <:< Single): String = s"fs://${location.bucket}/$path"
def getPaths()(implicit gp: GetPaths): Seq[String] = gp.getPaths()

private trait GetPaths {
def getPaths(): Seq[String]
}
private object GetPaths {
implicit def single(implicit ev: L <:< Single): GetPaths = () => Seq(getSinglePath())
implicit def multi(implicit ev: L <:< Multi): GetPaths = () => location.buckets.map(bucket => s"fs://${bucket}/$path")
}
}
现在 GetPaths是零参数 type classmagnet pattern 略有相似.

关于scala - 如何避免在 Scala 中调用 asInstanceOf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62716323/

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