How to use an implicit Scala class in Java

I have a Scala Implicit class from the RecordService API that I wanted to use in a Java file.

package object spark { implicit class RecordServiceContext(ctx: SparkContext) { def recordServiceTextFile(path: String) : RDD[String] = { new RecordServiceRDD(ctx).setPath(path) .map(v => v(0).asInstanceOf[Text].toString) } } } 

Now I am trying to import this into a Java file using the import below.

 import com.cloudera.recordservice.spark.*; 

But I can not use recordServiceTextFile ("path") from sparkContext.

In Scala, imports are slightly different and work.

+5
source share
4 answers

Here is a simple definition of an implicit class in a package object

 package object spark { implicit class Ext(param: Int) { def a = param + 1 } } 

and here is how you can use it from java

 public class Test { public static void main(String[] args) { spark.package$.MODULE$.Ext(123).a(); } } 

so you can basically use RecordServiceContext as a method that wraps your SparkContext and adds an extra method that you can call. This is an optimization for implicit classes.

It will be something like this:

 SparkContext c = ??? RDD<String> rdd = com.cloudera.recordservice.spark.package$.MODULE$.RecordServiceContext(c) .recordServiceTextFile("asdf"); 
+6
source

A package object spark compiled into the package class in the spark package. The implicit RecordServiceContext class will be compiled for the static method RecordServiceContext (scala implicit def) in package and the package$RecordServiceContext class.

So the following code should do this:

 import com.cloudera.recordservice.spark.*; //some code RDD<String> rdd = package.RecordServiceContext(myContext).recordServiceTextFile(pathToFile); //some code 

But package is probably a reserved keyword, and Java, as I know, cannot escape them. Therefore, you will need to do some reflection to call the RecordServiceContext method.

+1
source
  SparkContext ctx = ... RecordServiceContext rsct = new RecordServiceContext(ctx) recordServiceTextFile("/your_path") 
0
source

That should do it.

 String s = new spark.RecordServiceContext("safa").recordServiceTextFile("dsf"); 

I changed the signatures, though.

My Scala class is as follows:

 object spark { implicit class RecordServiceContext(ctx: String) { def recordServiceTextFile(path: String) : String = { "test" } } } 

My java class looks like this:

  public class TestScalaCall { public static void main(String args[]){ String s = new spark.RecordServiceContext("safa").recordServiceTextFile("dsf"); } } 

Change ---

So, a quick look at the Scala change requests shows us this .

They actually work on creating a class defined in the package object , in the same way as defining it in a regular package . But this is for release not yet 2.12 .

Thus, the recommendation they give is only absolutely necessary classes / objects that do not need external interaction inside the package objects. Otherwise, save them in regular packages. Therefore, for now, you do not need to use the package object construct.

In addition, you should consider: "Does it make sense to define something that is accessible externally inside the package object?"

0
source

Source: https://habr.com/ru/post/1246690/


All Articles