2016-04-08 15 views
5

Mam klasę Scala Implicit z usługi API RecordService, której chciałem użyć w pliku Java.Jak używać domyślnej klasy Scala w Javie

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

} 

Teraz próbuję zaimportować to w pliku Java z wykorzystaniem poniżej importu.

import com.cloudera.recordservice.spark.*; 

ale nie jestem w stanie wykorzystać recordServiceTextFile ("ścieżka") z sparkContext.

W Scala import jest trochę inny i działa.

+1

nie widzę niejawny klasę. –

+0

Importowanie kodu Scala w kodzie Java nie jest prostą operacją dla moich oczu. Wymaga to zrozumienia wewnętrznych elementów javac. Również pytanie nie jest jasne. Czy możesz być bardziej jasny na pytanie? Im bardziej "pełne" pytanie, tym lepsza jest odpowiedź. –

+0

@Ramesh Nie ma za co, ale to nie byłem ja. –

Odpowiedz

6

Oto prosta definicja niejawny klasy w pakiecie obiektu

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

i oto jak można go używać z Java

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

więc można w zasadzie używać RecordServiceContext jako metoda, która owija swoje SparkContext i dodaje dodatkową metodę, którą możesz wywołać. To jest optymalizacja dla niejawnych klas.

To byłoby coś takiego:

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

Dzięki, działa dobrze .. – Shankar

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

To powinno wystarczyć.

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

Zmieniłem jednak podpisy.

klasa

My Scala wygląda tak,

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

Moja klasa java wygląda tak,

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

Edycja ---

Tak szybkie spojrzenie zmiany Scala żąda przedstawienia nas this.

W rzeczywistości pracują nad tym, aby klasa zdefiniowana pod numerem package object zachowywała się tak samo, jak zdefiniowanie jej w zwykłym package. Ale to jest przeznaczone do jeszcze nie wydania 2.12.

Tak więc zalecenie, które wydaje, jest absolutnie niezbędne klasy/obiekty, które nie wymagają żadnej zewnętrznej interakcji wewnątrz obiektów pakietu. W przeciwnym razie przechowuj je w regularnych opakowaniach. Więc na razie nie należy używać konstrukcji package object.

Również punkt warto zastanawiać „Czy to naprawdę ma sens, aby zdefiniować coś, co jest dostępne na zewnątrz wewnątrz obiektu pakietu?”

+0

Twoja domniemana klasa nie ma "pakietu" przed "obiektem iskrą", to jest główny problem, z którym się borykam ... – Shankar

+0

Dodałem wyjaśnienie w odpowiedzi. To jest coś, nad czym pracuje zespół SCALA. –

1

package object spark jest kompilowany do klasy package w pakiecie spark. Domyślna klasa RecordServiceContext zostanie skompilowana do statycznej metody RecordServiceContext (która jest niejawną defektem scala) w package i klasie package$RecordServiceContext.

więc następujący kod powinien zrobić:

import com.cloudera.recordservice.spark.*; 

//some code 

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

//some code 

Ale package jest prawdopodobnie zarezerwowane słów kluczowych, Java i nie ma możliwości ucieczki je jako o ile wiem. Musisz więc zastanowić się, aby wywołać metodę RecordServiceContext.