Reputation: 23
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?
Upvotes: 2
Views: 342
Reputation: 23046
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"
}
Upvotes: 4