Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a Java self-bounded class in Scala

Tags:

java

scala

Say I have this self-bounded java class:

public class SelfBounded<SELF extends SelfBounded<SELF>> {
    public String testField = "TEST";

    public SelfBounded() {

    }

    public SELF testMethod() {
        return (SELF) this;
    }
}

In Java we can write this:

public class SelfBoundedMainJava {
    public static void main(String[] args) {
        SelfBounded selfBounded = new SelfBounded();
        System.out.println(selfBounded.testField);
        System.out.println(selfBounded.testMethod().testField);
    }
}

This code gives me 2x "TEST" as I expect.

But I'm struggling to write the same in scala:

If I do not pass the type it becomes a SelfBounded[Nothing]. But trying to use the SelfBounded type such as in ': SelfBounded[SelfBounded]', it gives me troubles because of the recursive nature and the compiler tells me each 'SelfBounded' needs a type parameter.

object SelfBoundedMainScala extends App {
  // here the type of selfBounded1 is SelfBounded[Nothing]
  val selfBounded1 = new SelfBounded()
  println(selfBounded1.testField)
  // does not work since testMethod() returns a Nothing
  //println(selfBounded1.testMethod().testField)

  // trying to set the type of the selfBounded variable gives me issues because of the recursive type
  // does not compile 'class SelfBounded takes type parameters'
  // val selfBounded2: SelfBounded[SelfBounded] = new SelfBounded()
  // same issue
  // val selfBounded3 = new SelfBounded[SelfBounded]()
}

Is there any way to accomplish the Java main class in Scala, without changing the SelfBounded class definition?

Note: This is a stripped down example while trying to use testcontainers-java in Scala.

like image 381
R Pieters Avatar asked Mar 24 '26 19:03

R Pieters


1 Answers

When you write SelfBounded selfBounded = new SelfBounded() in Java, you are using raw types, which exist only for compatibility with pre-generics code. Don't do that. The correct way is to extend SelfBounded:

class SelfBounded1 extends SelfBounded<SelfBounded1> {}

public class SelfBoundedMainJava {
    public static void main(String[] args) {
        // or SelfBounded<?> selfBounded
        SelfBounded1 selfBounded = new SelfBounded1();
        System.out.println(selfBounded.testField);
        System.out.println(selfBounded.testMethod().testField);
    }
}

Same in Scala, except it doesn't support raw types, since it had type parameters since beginning:

object SelfBoundedMainScala extends App {
  class SelfBounded1 extends SelfBounded[SelfBounded1]

  val selfBounded1 = new SelfBounded1()
  println(selfBounded1.testField)
  println(selfBounded1.testMethod().testField)
}
like image 86
Alexey Romanov Avatar answered Mar 27 '26 08:03

Alexey Romanov