W Scali, Jak mogę podklasować klasę Java z wieloma konstruktorami?

Załóżmy, że mam klasę Javy z wieloma konstruktorami:

class Base {
    Base(int arg1) {...};
    Base(String arg2) {...};
    Base(double arg3) {...};
}

Jak mogę rozszerzyć go w Scali i nadal zapewnić dostęp do wszystkich trzech konstruktorów bazy? W Scali podklasa może wywoływać tylko jeden z konstruktorów klasy superklasy. Jak mogę obejść tę zasadę?

Załóżmy, że Klasa Java jest kodem dziedziczonym, którego nie mogę zmienić.

Author: Seth Tisue, 2010-07-21

4 answers

Łatwo zapomnieć, że cecha może rozszerzyć klasę. Jeśli użyjesz cechy, możesz odłożyć decyzję o wywołaniu konstruktora, w następujący sposób:

trait Extended extends Base {
  ...
}

object Extended {
  def apply(arg1: Int) = new Base(arg1) with Extended
  def apply(arg2: String) = new Base(arg2) with Extended
  def apply(arg3: Double) = new Base(arg3) with Extended
}

Cechy mogą same w sobie nie mieć parametrów konstruktora, ale można to obejść, używając zamiast tego elementów abstrakcyjnych.

 87
Author: Seth Tisue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-21 13:57:15

Edytuj - to jest z pytania na liście mailingowej scala, które myślałem, że został powielony tutaj. Moja odpowiedź dotyczy dostarczenia trzech różnych konstruktorów (tj. replikacji projektu Java), a nie rozszerzenia klasy

Zakładając, że każdy z konstruktorów ostatecznie tworzy Stan S aby utworzyć obiekt towarzyszący za pomocą metod "statycznych", należy utworzyć ten stan

object Base {
  private def stateFrom(d : Double) : S = error("TODO")
  private def stateFrom(s : Str) : S = error("TODO")
  private def stateFrom(i : Int) : S = error("TODO")
} 

Następnie utwórz prywatny konstruktor biorąc stan i (public) overloaded constructors that defer to the primary constructor

import Base._
class Base private(s : S) { //private constructor takes the state
  def this(d : Double) = this(stateFrom(d)) 
  def this(str : String) = this(stateFrom(str))
  def this(i : Int) = this(stateFrom(i))
  //etc
}
 5
Author: oxbow_lakes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-21 14:16:05

Jest to głupia odpowiedź, która prawdopodobnie zadziałałaby nieco, ale może być zbyt dużym wysiłkiem, jeśli Klasa Java ma zbyt wiele konstruktorów, ale:

Napisz podklasę w Javie, która implementuje konstruktor, który pobiera wszystkie dane wejściowe, które Inne konstruktory wykonałyby i wywołuje odpowiedni konstruktor swojej superklasy w oparciu o obecność lub brak danych wejściowych (poprzez użycie "null" lub jakiegoś rodzaju wartości sentinel), a następnie podklasę tę klasę Javy w Scali i przypisać wartości sentinel jako domyślne parametry.

 2
Author: JAB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-21 13:59:15

Wybrałbym najbardziej ogólny (w tym przypadku String) i sam dokonałbym wewnętrznej konwersji, jeśli spełnia inne kryteria.

Choć przyznaję, że nie jest to najlepsze rozwiązanie i coś wydaje mi się w tym złe. :-(

 1
Author: corsiKa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-21 13:36:34