如何避免在 Scala 中调用 asInstanceOf



这是我代码的简化版本。

我怎样才能避免打电话给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}")
}

通常,类型类是模式匹配的编译时替换。

我必须公开getSinglePathpathval,以便在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是零参数类型类,与磁铁图案略有相似。

相关内容

  • 没有找到相关文章

最新更新