Surcharge du constructeur Scala?

135

Comment fournir des constructeurs surchargés dans Scala?

Landon Kuhn
la source

Réponses:

186

Il convient de mentionner explicitement que les constructeurs auxiliaires de Scala doivent soit appeler la réponse du constructeur principal (comme dans landon9720), soit un autre constructeur auxiliaire de la même classe, comme première action. Ils ne peuvent pas simplement appeler le constructeur de la superclasse explicitement ou implicitement comme ils le peuvent en Java. Cela garantit que le constructeur principal est le seul point d'entrée de la classe.

class Foo(x: Int, y: Int, z: String) {  
  // default y parameter to 0  
  def this(x: Int, z: String) = this(x, 0, z)   
  // default x & y parameters to 0
  // calls previous auxiliary constructor which calls the primary constructor  
  def this(z: String) = this(0, z);   
}
Jon McAuliffe
la source
@Jon McAuliffe: Mauvais exemple? Sans deuxième et troisième constructeurs, l'utilisateur peut toujours appeler new Foo(x=2,z=4)et new Foo(z=5)si vous changez votre première ligne enclass Foo(x: Int = 0, y: Int = 0, z: String) {
user2987828
Les arguments nommés / par défaut n'arrivent pas avant Scala 2.8.
Jon McAuliffe
2
Il serait intéressant de mentionner comment utiliser un constructeur de surcharge. Ce n'est pas anodin que le newmot-clé soit nécessaire même pour les classes de cas.
Readren
33
 class Foo(x: Int, y: Int) {
     def this(x: Int) = this(x, 0) // default y parameter to 0
 }
Landon Kuhn
la source
16

Depuis Scala 2.8.0, vous pouvez également avoir des valeurs par défaut pour les paramètres du constructeur et de la méthode. Comme ça

scala> class Foo(x:Int, y:Int = 0, z:Int=0) {                           
     | override def toString() = { "Foo(" + x + ", " + y + ", " + z + ")" }
     | }
defined class Foo

scala> new Foo(1, 2, 3)                                                    
res0: Foo = Foo(1, 2, 3)

scala> new Foo(4)                                                          
res1: Foo = Foo(4, 0, 0)

Les paramètres avec des valeurs par défaut doivent venir après ceux sans valeurs par défaut dans la liste des paramètres.

Jörgen Lundberg
la source
3
Cela ne fonctionne pas pour les valeurs par défaut non triviales. donc class Foo(val x:Int, y:Int=2*x)ne fonctionne pas.
sous
@ Jörgen Lundberg: vous avez écrit Les paramètres avec des valeurs par défaut doivent venir après ceux sans valeurs par défaut dans la liste des paramètres. C'est faux, new Foo(x=2,z=4)imprimera Foo(2,0,4).
user2987828
@ user2987828 ce que je voulais dire, c'est que vous ne pouvez pas écrire de nouveau Foo (12, x = 2), vous devez écrire un nouveau Foo (x = 2, 12). Vous pouvez écrire un nouveau Foo (12, y = 2), puis vous obtiendrez Foo (12, 2, 0)
Jörgen Lundberg
10

En regardant mon code, je me suis soudainement rendu compte que j'avais une sorte de surcharge d'un constructeur. Je me suis alors souvenu de cette question et suis revenu pour donner une autre réponse:

Dans Scala, vous ne pouvez pas surcharger les constructeurs, mais vous pouvez le faire avec des fonctions.

De plus, beaucoup choisissent de faire de la applyfonction d'un objet compagnon une fabrique pour la classe respective.

En rendant cette classe abstraite et en surchargeant la applyfonction pour implémenter-instancier cette classe, vous avez votre «constructeur» surchargé:

abstract class Expectation[T] extends BooleanStatement {
    val expected: Seq[T]}

object Expectation {
    def apply[T](expd:     T ): Expectation[T] = new Expectation[T] {val expected = List(expd)}
    def apply[T](expd: Seq[T]): Expectation[T] = new Expectation[T] {val expected =      expd }

    def main(args: Array[String]): Unit = {
        val expectTrueness = Expectation(true)}
}

Notez que je définis explicitement chacun applypour retourner Expectation[T], sinon cela renverrait un type de canard Expectation[T]{val expected: List[T]}.

mouton volant
la source
0

Essaye ça

class A(x: Int, y: Int) {
  def this(x: Int) = this(x, x)
  def this() = this(1)
  override def toString() = "x=" + x + " y=" + y
  class B(a: Int, b: Int, c: String) {
    def this(str: String) = this(x, y, str)
    override def toString() =
      "x=" + x + " y=" + y + " a=" + a + " b=" + b + " c=" + c
  }
}
anish
la source