2011-10-19 33 views
11

w Scala, możemy napisaćCo to jest odpowiednik Java obiektu Scala?

object Foo { def bar = {} } 

Jak to jest realizowane przez kompilator? Jestem w stanie wywołać Foo.bar(); z Java ale new Foo(); z Java daje błąd cannot find symbol symbol: constructor Foo()

  • Czy te singletons wsparcia JVM natywnie?
  • Czy można mieć klasę w Javie, która nie ma konstruktora?

Uwaga: tutaj jest wyjście kodu przez scalac -print

package <empty> { 
    final class Foo extends java.lang.Object with ScalaObject { 
    def bar(): Unit =(); 
    def this(): object Foo = { 
     Foo.super.this(); 
    () 
    } 
    } 
} 

Odpowiedz

11

Wsparcie dla pojedynczych nie jest na poziomie języka, ale język zapewnia wystarczającą ilość urządzeń do tworzenia je bez żadnych problemów.

Rozważmy następujący kod:

public class Singleton { 
    private static final Singleton instance = new Singleton(); 

    // Private constructor prevents instantiation from other classes 
    private Singleton() {} 

    public static Singleton getInstance() { 
     return instance; 
    } 
} 

To jest przykład z Wikipedii, która wyjaśnia, w jaki sposób można dokonać Singleton. Instancja jest przechowywana w prywatnym polu, konstruktor jest niedostępny poza klasą, metoda zwraca to pojedyncze wystąpienie.

Jak dla konstruktorów: każda klasa ma domyślnie tzw domyślnego konstruktora która przyjmuje żadnych argumentów i po prostu wywołuje konstruktor no-args z nadklasy. Jeśli nadklasa nie ma żadnego dostępnego konstruktora bez argumentów, będziesz musiał napisać jawny konstruktor.

Zatem klasa musi mieć konstruktor, ale nie trzeba go pisać, jeśli nadklasa ma konstruktor no-args.

+0

ah tak Sztuką jest, aby prywatnej konstruktora. – Jus12

21

Podczas kompilowania kodu, kompilator Scala produkuje odpowiednik następującego kodu Java:

public final class Foo { 
    private Foo() {} // Actually, Foo doesn't have constructor at all 
        // It can be represented in bytecode, 
        // but it cannot be represented in Java language 

    public static final void bar() { 
     Foo$.MODULE$.bar(); 
    } 
} 

public final class Foo$ implements ScalaObject { 
    public static final Foo$ MODULE$; 
    static { 
     new Foo$(); 
    } 
    private Foo$() { MODULE$ = this; } 
    public final void bar() { 
     // actual implementation of bar() 
    } 
} 

Tutaj Foo$ jest rzeczywiste wdrożenie Singleton, natomiast Foo zapewnia static metodę interakcji z Java.

+0

Czy jest jakiś sposób, aby zobaczyć "pośredni" kod Java, jak pokazano? Czy użyłeś dekompilatora do wygenerowania go? – Jus12

+1

@ Jus12: Być może niektóre dekompilatory są w stanie to pokazać, ale zrekonstruowałem je ręcznie z wyjścia 'javap -c -private Foo' /' javap -c -private Foo $ ' – axtavt

Powiązane problemy