Как использовать неявный класс Scala в Java



У меня есть неявный класс Scala от RecordService API, который я хотел использовать в файле Java.





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)
}
}

}


Теперь я пытаюсь импортировать это в файл Java, используя ниже импорт.





import com.cloudera.recordservice.spark.*;


Но я не могу использовать recordServiceTextFile ("путь") из sparkContext.



В Scala импорт мало отличается и его работа.

609   4  

4 ответов:

Вот простое определение неявного класса в объекте пакета

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

И вот как вы можете использовать его из java

public class Test {
    public static void main(String[] args) {
        spark.package$.MODULE$.Ext(123).a();
    }
}
Таким образом, вы можете использовать RecordServiceContext в качестве метода, который обертывает ваш SparkContext и добавляет дополнительный метод, который вы можете вызвать. Это оптимизация для неявных классов.

Это было бы примерно так:

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

A package object spark компилируется в класс package в пакете spark. Неявный класс RecordServiceContext будет скомпилирован в статический метод RecordServiceContext (это неявный def scala) в package и класс package$RecordServiceContext.

Так что следующий код должен сделать это:

import com.cloudera.recordservice.spark.*;

//some code

RDD<String> rdd = package.RecordServiceContext(myContext).recordServiceTextFile(pathToFile);

//some code

Но package, вероятно, зарезервированное ключевое слово, и Java не имеет способа избежать их, насколько я знаю. Поэтому вам придется немного поразмыслить, чтобы вызвать метод RecordServiceContext.

 SparkContext ctx = ...
 RecordServiceContext rsct = new RecordServiceContext(ctx)
 recordServiceTextFile("/your_path")

Это должно сработать.

String s = new spark.RecordServiceContext("safa").recordServiceTextFile("dsf");
Однако я изменил подписи.

Мой класс Scala выглядит так,

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

Мой класс java выглядит так,

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

Edit - - -

Поэтому быстрый просмотр запросов на изменение Scala показывает намЭто .

На самом деле они работают над тем, чтобы класс, определенный в соответствии с package object, вел себя так же, как и при определении его внутри регулярного package. Но это нацелено на еще не выпущенный релиз 2.12.

Так что рекомендация, которую они дают, состоит в том, чтобы сохранить только абсолютно необходимые классы / объекты, которые не нуждаются в каком-либо внешнем взаимодействии внутри объектов пакета. В противном случае держите их под обычными пакетами. Поэтому пока вам не нужно использовать конструкцию package object.

Кроме того, стоит задуматься над вопросом "действительно ли имеет смысл определять что-то, что доступно снаружи внутри объекта пакета ? "

Comments

    Ничего не найдено.