I have a Scala class:
class Foo(val x:String = "default X", val y:String = "default Y" )
I want to call it from Java, but using the default parameters
Passing null
doesn't work (it assigns null
, as expected)
new Foo(null,null); //both are instantiated as null
This trick did work for me, but it's ugly, and I wonder if there is a better way:
Scala
class Foo(val x:String = "default X", val y:String = "default Y" ) {
def this(x:Object) = this()
}
Java
new Foo(null); //no matter what I pass it should work
However I would like to get rid of the constructor overload trick, and use a 0 param constructor
Is that possible?
In Scala, we are allowed to make a primary constructor private by using a private keyword in between the class name and the constructor parameter-list.
If there are no constructors written for a class, Java provides a no-argument default constructor where the instance variables are set to their default values. For int and double variables, the default value used is 0, and for String and other object variables, the default is null.
Benefits. Supplying default constructor parameters has at least two benefits: You provide preferred, default values for your parameters. You let consumers of your class override those values for their own needs.
Scala case classes are just regular classes which are immutable by default and decomposable through pattern matching. It uses equal method to compare instance structurally. It does not use new keyword to instantiate object. All the parameters listed in the case class are public and immutable by default.
It seems, there is no such way: https://issues.scala-lang.org/browse/SI-4278
Issue: default no-args constructor should be generated for classes with all-optional arguments
...Lukas Rytz: in respect of language uniformity we decided not to fix this one - since it's a problem of interoperability with frameworks, we think it should not be fixed at the language level.
workarounds: repeat a default, or abstract over one, or put one default int the zero-argument constructor
Then Lukas proposes the same solution as you found:
class C(a: A = aDefault, b: B = C.bDefault) {
def this() { this(b = C.bDefault) }
}
object C { def bDefault = ... }
// OR
class C(a: A = aDefault, b: B) {
def this() { this(b = bDefault) }
}
There is a solution, please check out section "Default Arguments" from article: https://lampwww.epfl.ch/~michelou/scala/using-scala-from-java.html
It's possible to invoke both constructors and methods by passing the appropriate positional argument from java using .$default$[number] format.
Here scope is as follows:
Example:
import za.co.absa.spline.core.SparkLineageInitializer;
SparkLineageInitializer.SparkSessionWrapper lineage = SparkLineageInitializer.SparkSessionWrapper(spark);
lineage.enableLineageTracking(lineage.enableLineageTracking$default$1());
For this example the maven dependency is: groupId: za.co.absa.spline artifactId: spline-core version: 0.3.1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With