Как использовать неявный класс 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 импорт мало отличается и его работа.
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