Try a type class
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}")
}
Normally a type class is a compile-time replacement for pattern matching.
I had to make getSinglePath
public and path
a val
in order to provide access to them inside GetPaths
. If you don't want to do so you can make the type class nested into 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")
}
}
Actually we don't have to pass location
explicitly and we don't need 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")
}
}
Now GetPaths
is zero-parameter type class and slightly similar to magnet pattern.
gp.getPaths(SingleBucket("nottheonefrommyobject")
It doesn't seem a big win compared toprivate def getSinglePath(location: Single): String = s"fs://${location.bucket}/$path"
– Scuff