Scala: implementing method with return type of concrete instance -
i need way enforce method in abstract class have homecoming type of concrete class of object called on. mutual illustration copy()
method, , i'm using approach based on abstract types:
abstract class a(id: int) { type self <: def copy(newid: int): self } class b(id: int, x: string) extends a(id) { type self = b def copy(newid: int) = new b(newid, x) } class c(id: int, y: string, z: string) extends a(id) { type self = c def copy(newid: int) = new c(newid, y, z) }
i saw many approaches, including ones in this great answer. however, none of them forces implementation homecoming own type. example, next classes valid:
class d(id: int, w: string) extends a(id) { type self = def copy(newid: int) = new d(newid, w) // returns } class e(id: int, v: string) extends a(id) { type self = b def copy(newid: int) = new b(newid, "") }
the fact can causes that, if doing copies of objects of info have of given subclass of a
's:
// type error: seq[a] not seq[ca]! def createcopies[ca <: a](seq: seq[ca]): seq[ca] = seq.map(_.copy(gennewid()))
is there better, type-safe way can that?
edit: if possible, maintain ability create arbitrarily deep hierarchies of abstract classes. is, in previous example, i'm expecting able create abstract class a2
extends a
, , proceed create a2
's concrete subclasses. however, if simplifies problem (as it's case abstract types), not need farther extend concrete classes.
the solution think of one:
trait cancopy[t <: cancopy[t]] { self: t => type self >: self.type <: t def copy(newid: int): self } abstract class a(id: int) { self:cancopy[_] => def copy(newid: int): self }
the next compile:
class b(id: int, x: string) extends a(id) cancopy[b] { type self = b def copy(newid: int) = new b(newid, x) } class c(id: int, y: string, z: string) extends a(id) cancopy[c] { type self = c def copy(newid: int) = new c(newid, y, z) }
the next not compile:
class d(id: int, w: string) extends a(id) cancopy[d] { type self = def copy(newid: int) = new d(newid, w) // returns } class e(id: int, v: string) extends a(id) cancopy[e] { type self = b def copy(newid: int) = new b(newid, "") }
edit i forgot remove re-create method. might bit more generic:
trait strictself[t <: strictself[t]] { self: t => type self >: self.type <: t } abstract class a(id: int) { self:strictself[_] => def copy(newid:int):self }
scala abstract-type self-type
No comments:
Post a Comment