преобразовать код java в scala - изменение сигнатур метода

Пытаясь преобразовать некоторый код java в scala, я сталкиваюсь с проблемой другой сигнатуры метода, которая отлично скомпилирована в мире java:

Следующий код в Java (из https://github.com/DataSystemsLab/GeoSpark/blob/master/babylon/src/main/java/org/datasyslab/babylon/showcase/Example.java#L122-L126)

visualizationOperator = new ScatterPlot(1000,600,USMainLandBoundary,false,-1,-1,true,true);
visualizationOperator.CustomizeColor(255, 255, 255, 255, Color.GREEN, true);
visualizationOperator.Visualize(sparkContext, spatialRDD);
imageGenerator = new SparkImageGenerator();
imageGenerator.SaveAsFile(visualizationOperator.distributedVectorImage, "file://"+outputPath,ImageType.SVG);

Переводится на https://github.com/geoHeil/geoSparkScalaSample/blob/master/src/main/scala/myOrg/visualization/Vis.scala#L45-L57

val vDistributedVector = new ScatterPlot(1000, 600, USMainLandBoundary, false, -1, -1, true, true)
vDistributedVector.CustomizeColor(255, 255, 255, 255, Color.GREEN, true)
vDistributedVector.Visualize(s, spatialRDD)
sparkImageGenerator.SaveAsFile(vDistributedVector.distributedVectorImage, outputPath + "distributedVector", ImageType.SVG)

Что вызовет следующую ошибку:

overloaded method value SaveAsFile with alternatives:
[error]   (x$1: java.util.List[String],x$2: String,x$3: org.datasyslab.babylon.utils.ImageType)Boolean <and>
[error]   (x$1: java.awt.image.BufferedImage,x$2: String,x$3: org.datasyslab.babylon.utils.ImageType)Boolean <and>
[error]   (x$1: org.apache.spark.api.java.JavaPairRDD,x$2: String,x$3: org.datasyslab.babylon.utils.ImageType)Boolean
[error]  cannot be applied to (org.apache.spark.api.java.JavaPairRDD[Integer,String], String, org.datasyslab.babylon.utils.ImageType)
[error]     sparkImageGenerator.SaveAsFile(vDistributedVector.distributedVectorImage, outputPath + "distributedVector", ImageType.SVG)

К сожалению, я не совсем уверен, как это исправить/как правильно вызвать метод в scala.


person Georg Heiler    schedule 26.04.2017    source источник


Ответы (2)


Это проблема ImageGenerator, унаследованная SparkImageGenerator. Как видите, здесь у него есть метод

public boolean SaveAsFile(JavaPairRDD distributedImage, String outputPath, ImageType imageType)

который использует необработанный тип (JavaPairRDD без <...>). Они существуют в первую очередь для совместимости с кодом до Java 5 и обычно не должны использоваться иначе. Для этого кода, безусловно, нет веской причины, так как он фактически ожидает параметры определенного типа. Использование необработанных типов просто теряет безопасность типов. Возможно, некоторые подклассы (текущие или потенциальные) могут переопределить его и ожидать другие параметры типа, но это было бы неправильным использованием наследования, и должно быть лучшее решение.

Scala никоим образом не поддерживает необработанные типы, поэтому вы не можете вызвать из него этот метод (насколько мне известно). В качестве обходного пути вы можете написать оболочку на Java, которая использует правильные типы, и вызвать эту оболочку из Scala. Я неправильно запомнил, она расширяет классы Java, расширяя необработанные типы, что было невозможно, и даже в этом случае есть обходные пути.

Возможно, вы сможете вызвать его с помощью явного приписывания типа (предпочтительнее, чем приведение):

sparkImageGenerator.SaveAsFile(
  (vDistributedVector.distributedVectorImage: JavaPairRDD[_, _]), 
  outputPath + "distributedVector", ImageType.SVG)

Но, учитывая, что в сообщении об ошибке отображается только JavaPairRDD, я не особо ожидаю, что это сработает. Если это не сработает, я все равно буду использовать оболочку Java.

person Alexey Romanov    schedule 26.04.2017
comment
Я думал, что необработанные типы интерпретируются в Scala как экзистенциальные типы. - person Jasper-M; 26.04.2017
comment
Угу, вы правы, конечно. Проблема в том, что в этом конкретном случае он, похоже, не интерпретирует его таким образом, потому что сообщение об ошибке показывает его как необработанный тип (x$1: org.apache.spark.api.java.JavaPairRDD,...). - person Alexey Romanov; 26.04.2017
comment
Я не уверен, что это проблема с сообщением об ошибке или с проверкой типов. На самом деле у меня есть запрос на вытягивание, который должен улучшить некоторые сообщения об ошибках, связанных с необработанными типами: github.com/scala/ скала/тянуть/5847 - person Jasper-M; 26.04.2017

Принятый ответ верен, говоря, что следует избегать необработанных типов. Однако Scala может взаимодействовать с кодом Java, имеющим необработанные типы. Scala интерпретирует необработанный тип java.util.List как экзистенциальный тип java.util.List[_].

Возьмем, к примеру, этот код Java:

// Test.java
import java.util.Map;

public class Test {
  public boolean foo(Map map, String s) {
    return true;
  }
}

Затем попробуйте вызвать его из Scala:

Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_131).
Type in expressions for evaluation. Or try :help.

scala> import java.util.{Map,HashMap}
import java.util.{Map,HashMap}

scala> new Test().foo(new HashMap[String,Integer], "a")
res0: Boolean = true

scala> val h: Map[_,_] = new HashMap[String,Integer]
h: java.util.Map[_, _] = {}

scala> new Test().foo(h, "a")
res1: Boolean = true

Так что, похоже, должна быть какая-то другая проблема.

person Jasper-M    schedule 26.04.2017