Collections of Traits with types generics in Scala 2.10 -


i'm trying build collections of objects, defined @ run time , using type generics, referring superclass (well, trait), i'm having tough time transforming them child objects. example code , results:

trait mytrait[t] {   def f(x: t): int }  class foo extends mytrait[double] {   def f(x: double) = 1 }  class bar extends mytrait[string] {   def f(x: string) = 2 }  val fooinstance: foo = new foo val barinstance: bar = new bar val mytraitlist: list[mytrait[_]] = list(fooinstance, barinstance)  println(fooinstance.getclass) // prints "class myexample$foo" println(barinstance.getclass) // prints "class myexample$bar"  println(mytraitlist(0).getclass) // prints "class myexample$foo", list preserving object classes , not "mytrait[_]" println(mytraitlist(1).getclass) // prints "class myexample$bar", again, preserving object class  println(fooinstance.f(1.0)) // prints "1" println(barinstance.f("blah")) // prints "2"  println(mytraitlist(0).f(1.0)) // things break: // "type mismatch; found : double(1.0) required: _$3 type _$3" // so, list element knows it's instance of foo (as indicated getclass), has lost overloaded definition of f  println(mytraitlist(1).f("blah")) // same error occurs on bar instance: // "type mismatch; found : string("blah") required: _$3 type _$3" 

if hard-code mytraitlist(0).asinstanceof[foo].f(1.0), (predictably) works fine. so, tried create function @ run time:

def casttocorrectchildclass(o: mytrait[_], label: char): mytrait[_] = {   return label match {     case 'f' => o.asinstanceof[foo]     case 'b' => o.asinstanceof[bar]     case _ => o   } } 

unfortunately, subject same problems:

println(casttocorrectchildclass(mytraitlist(0), 'f').f(1.0)) // type mismatch; found : double(1.0) required: _$2 type _$2 

one solution make list[mytrait[any]] store instances , make type parameter covariant: trait mytrait[+t]. unfortunately, in real-world code, need invariant other reasons, can't use workaround. i've tried using classtags , typetags remember child class thinking reflection-related problem, didn't have luck (and suspect that's not intended use case these, anyway, though perhaps i'm mistaken).

any suggestions? i'd love have flexible collection of unknown number (so, no tuples) of child objects extending same trait different types per user input gathered @ run time, , i'm happy accept trade-off of doing bookkeeping ensure don't mis-cast (or mis-asinstanceof) object incorrect type, can't seem working. in advance!

i not sure want do, problem facing because type of mytraitlist similar having list[mytrait[any]]. since type _ compiler doesn't know if it's bar or foo. thankfully scala provides pattern matching allows condition on type of object.

solution 1

def conditionaldo(x: mytrait[_]) = {     x match {         case i: foo => println("doing foo() stuff")         case j: bar => println("doing bar() stuff")         case _ => println("error!")     } }  mytraitlist.foreach(conditionaldo) 

solution 2

trait mytrait {   def f(x: any): int }  class foo extends mytrait {   def f(x: any) = {     x match {        case i: int => 1        case _ => -1     }   } }  class bar extends mytrait {   def f(x: any) = {     x match {        case j: string => 2        case _ => -1     }   } }  val fooinstance: foo = new foo val barinstance: bar = new bar  val mytraitlist: list[mytrait] = list(fooinstance, barinstance) mytraitlist(0).f(1) // returns 1 mytraitlist(1).f("s") // returns 2 

Comments

Popular posts from this blog

PHP DOM loadHTML() method unusual warning -

python - How to create jsonb index using GIN on SQLAlchemy? -

c# - TransactionScope not rolling back although no complete() is called -