scala - Inheritance of immutable return types when extending traits in multiple levels -


i have following trait hierarchy. traita root trait, , given want data structures immutable, function commonupdatefunction() has generic return type. not sure if best way. have 2 other traits extend it, adding 2 other functions. classes extend one, classes extend other, classes need extend both.

however, running problem because of generic type thing getting illegal inheritance, when in reality doing right type when updating data structure new one.

furthermore seems cannot pass traita parameter because of generic type.

trait traita[t <: traita[t]] {    self : t =>     def commonupdatefunction() : t }  trait traitb extends traita[traitb] {    def somefunctionb() : integer = { /// code } }  trait traitc extends traita[traitc] {    def somefunctionc() : unit = { /// code }  }  class classb extends traitb  {    def commonupdatefunction() : classb = { /// code }  }  class classc extends traitc {    def commonupdatefunction() : classc = { /// code } }   class classa extends traitb traitc  //**this causes illegal inheritance** {    def commonupdatefunction() : classa = { /// code } }  

what right way achieve inheritance on 2 traits while @ same time having immutable updating of data structures right types?

type parameters aren't problem here, problem classa tries mix in 3 copies of commonfunction(), differ return type:

class classa extends traitb traitc {   def commonfunction() : classa = { /// code }   def commonfunction() : classb = { /// code }    def commonfunction() : classc = { /// code }  }  

although jvm does allow overloading on return type, isn't permitted @ compile time - there's chance confusion (especially if type inference involved).

the solution use f-bounded polymorphism (as did commonupdatefunction()), it's impossible show how here given commonfunction() definitions concrete.

it lot see more "real" code!


update: based on new information comments.

instead of type parameter might find life easier abstract type member. using repr (for "repr"esentation) common enough convention , used in collections lib; make sure abstract type member has bound!

stick other common attributes in here well:

trait employee {   type repr <: employee    def name : string   def id   : int    def withname(name: string) : repr   def withid(id: int) : repr } 

sub-traits follow similar pattern. there's no need re-declare other abstract members keep signature. can introduce other members refine types here.

trait managingemployee extends employee {   type repr <: managingemployee   def numberofreports: int   def withnumberofreports(x: int) : repr }  trait skilledemployee extends employee {   type repr <: skilledemployee    def skill: string } 

now make leaf nodes of our type tree concrete. case classes work here, though there sadly duplication (macros possibly help, that's different question).

note how name , id made concrete class params, repr type made explicit via = sign, , abstract methods have explicitly re-defined in each leaf class:

case class hrmanager(   name            : string,   id              : int,   numberofreports : int ) extends managingemployee {   type repr = hrmanager   def withname(name: string) = this.copy(name = name)   def withid(id: int) = this.copy(id = id)   def withnumberofreports(x: int) = this.copy(numberofreports = id) }  case class technician(name: string, id: int) extends skilledemployee {   type repr = technician   def withname(name: string) = this.copy(name = name)   def withid(id: int) = this.copy(id = id)   val skill = "programming" }   case class technicalmanager(   name            : string,   id              : int,   numberofreports : int ) extends skilledemployee managingemployee {   type repr = technicalmanager    def withname(name: string) = this.copy(name = name)   def withid(id: int) = this.copy(id = id)   def withnumberofreports(x: int) = this.copy(numberofreports = id)   val skill = "software architecture" }  

Comments

Popular posts from this blog

python - Subclassed QStyledItemDelegate ignores Stylesheet -

java - HttpClient 3.1 Connection pooling vs HttpClient 4.3.2 -

SQL: Divide the sum of values in one table with the count of rows in another -