Question

I have a type that i use that use for ducktyping:

type t={
   def x:Int
 ...
}
class t2 {
 def x:Int=1
}
def myt:t=new t2 //ducktyping

I want to write a trait that is forced to interface the type but this does NOT work:

trait c extends t { //interface DOES NOT COMPILE
  def x:Int=1
}

On the other hand: if i write a trait t1 instead of type t then i lose the ducktyping feature:

trait t1 {
 def x:Int
}
type t=t1
trait c extends t1 { // t1 can be used as interface
  def x:Int=1
}
def myt:t=new t2  // DOES NOT COMPILE since t1 is expected

So how can i use both ducktyping and interfacing?

Was it helpful?

Solution

You can only extend class-like entities in Scala (ie. classes, traits, Java interfaces) not types in general (ie. structural types, type parameters or members). However, you can self-type to all of these. That means that we can rewrite your non-compiling trait c as follows,

trait c { self : t =>
  def x : Int = 1
}

Within the body of c the type of this is now known to be t, ie., known to conform to the structural type { def x : Int }, and it will only be possible to mix c into a class which does actually conform to that structural type (either by implementing the signature directly or, if abstract, by reasserting the self-type and propagating the obligation to the eventual concrete class),

type t = { def x : Int }

trait c { self : t => }

class t2 extends c {  // OK, t2 conforms to t
  def x : Int = 1
}

def myt : t = new t2  // OK, as before

class t3 extends c {  // Error: t3 doesn't conform to c's self-type
  def y : String = "foo"
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top