Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala functional interface traits

Tags:

scala

I have a trait:

trait MyTrait extends (Int => MyTrait)

How can I restrict MyTrait in the extends to be any implementations of MyTrait?

like image 558
joesan Avatar asked Dec 06 '22 21:12

joesan


2 Answers

In scala, the Function type is covariant as denoted by +R in the Function1 signature:

trait Function1[-T1, +R] extends AnyRef

This means that what you have is right already. Having MyTrait extend (Int => MyTrait) (which is the same as Function1[Int, MyTrait) means that any type that extends MyTrait will have to implement an apply function that returns any instance of MyTrait.

The following would all be legal according to your current MyTrait signature:

class Foo extends MyTrait {
    def apply(x: Int): Foo = new Foo
}

class Bar extends MyTrait {
    def apply(x: Int): Foo = new Foo
}

class Baz extends MyTrait {
    def apply(x: Int): MyTrait = new MyTrait { def apply(y: Int) = new Baz }
}
like image 191
Dan Gallagher Avatar answered Dec 08 '22 10:12

Dan Gallagher


As Dan wrote the normal behaviour is to return any instance of MyTrait.

If you want to restrict it to only return an instance of the type of the current object you can do so:

trait MyTrait[T <: MyTrait[T]] extends (Int => T)

and then when you implement(copying from Dan)

class Foo extends MyTrait[Foo] {
    def apply(x: Int): Foo = new Foo
}

class Bar extends MyTrait[Bar] {
    def apply(x: Int): Foo = new Foo //Compile error
}

class Baz extends MyTrait[Baz] {
    def apply(x: Int): MyTrait = new MyTrait { def apply(y: Int) = new Baz }
}
like image 27
Meir Maor Avatar answered Dec 08 '22 12:12

Meir Maor