57 votes

Dans Scala, comment puis-je sous-classer une classe Java avec plusieurs constructeurs?

Supposons que j'ai une classe Java avec plusieurs constructeurs:

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

Comment puis-je l'étendre dans Scala tout en permettant l'accès aux trois constructeurs de Base? En Scala, une sous-classe ne peut appeler qu'un des constructeurs de sa super-classe. Comment puis-je contourner cette règle?

Supposons que la classe Java est un code hérité que je ne peux pas modifier.

89voto

Seth Tisue Points 9090

Il est facile d'oublier qu'un trait peut prolonger une classe. Si vous utilisez un trait, vous pouvez reporter la décision du constructeur à appeler, comme ceci:

 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
}
 

Les traits ne peuvent pas eux-mêmes avoir des paramètres de constructeur, mais vous pouvez contourner ce problème en utilisant plutôt des membres abstraits.

5voto

oxbow_lakes Points 70013

EDIT - c'est à partir d'une question sur la scala de mailing liste de ce que j'ai pensé de la même façon ici. Ma réponse a trait à la présentation de trois différents constructeurs (c'est à dire en reproduisant le dessin Java), et de ne pas étendre la classe

En supposant que chacun de vos constructeurs de créer, à terme, l' état S de l'objet, créer un compagnon objet avec "statique" des méthodes pour créer cet état

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

Puis créer un constructeur privé prise de l'état et (public) constructeurs surchargés qui reporter à la primaire constructeur

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
}

2voto

JAB Points 11053

C'est une réponse idiote qui serait probablement travailler un peu, mais peut-être trop d'effort si la classe Java a beaucoup trop de constructeurs, mais:

Écrire une sous-classe Java qui implémente un constructeur qui prend toutes les entrées de diverses autres constructeurs et les appels au bon constructeur de sa super-classe en fonction de la présence ou de l'absence d'intrants (via l'utilisation de "null" ou une sorte de sentinelle des valeurs), puis sous-classe de la classe Java de Scala et de céder la sentinelle des valeurs que les paramètres par défaut.

2voto

corsiKa Points 39442

Je choisirais le plus générique (dans ce cas, String) et ferais la conversion interne vous-même si elle répond aux autres critères.

Bien que j’admette que ce n’est pas la meilleure solution et que quelque chose me semble faux. :-(

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X