Search code examples
javascalastructural-typing

How define Structural Type that the method return this


I have a number of Builders which comes from library which the source code is auto generated in Java and beyond my control. These Builders are not related one to another, but they have a number of methods which are structurally exactly the same.

package a.b

public class Builder {
    public Builder setA(xxx) {}
    public Builder setB(yyy) {}
}

package a.c

public class Builder {
    public Builder setA(xxx) {}
    public Builder setB(yyy) {}
}

Using Scala's structural type, how can I return the builder for itself?

type StructurallyBuilder = {
    def setA(xxx): StructurallyBuilder
    def setB(yyy): StructurallyBuilder
}

When I want to use setA and setB on the StructurallyBuilder, the compiler complains that it cannot resolve.


Solution

  • It's not exactly straightforward, but I believe you can use F-bounded polymorphism to achieve that:

    type StructurallyBuilder[F <: StructurallyBuilder[F]] = {
      def setA(xxx: Int): F
      def setB(yyy: Int): F
    }
    

    You have to keep this complex signature when defining classes or methods taking those builders. For example:

    def setA[T <: StructurallyBuilder[T]](
      xxx: Int, 
      builder: StructurallyBuilder[T]
    ): T = builder.setA(xxx)
    

    But it seems you can use those methods normally:

    val bld: a.c.Builder = setA(10, new a.c.Builder())