Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instantiate a Scala class from Java, and use the default parameters of the constructor

Tags:

java

scala

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?

like image 457
Eran Medan Avatar asked Oct 24 '12 23:10

Eran Medan


People also ask

How do I create a class constructor in Scala?

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.

Where would you provide a default value for class's constructor parameter?

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.

What is the benefit of giving a constructor default arguments?

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.

What is case class in Scala with example?

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.


2 Answers

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) }
}
like image 186
Artem Shitov Avatar answered Oct 20 '22 20:10

Artem Shitov


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:

  • Class constructor: << ClassName >>.init$default$1 for the value of the first arguments default value set in the constructor definition default$2 for second arguments default value and so on.
  • Method call: object.methodName$default$1 to resolve the methods first parameters default value assigned in the method signature etc.

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

like image 35
Developer Avatar answered Oct 20 '22 20:10

Developer