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