Sobrecarga de construtor Scala?

135

Como você fornece construtores sobrecarregados no Scala?

Landon Kuhn
fonte

Respostas:

186

Vale mencionar explicitamente que os Construtores Auxiliares em Scala devem chamar a resposta do construtor primário (como em landon9720), ou outro construtor auxiliar da mesma classe, como sua primeira ação. Eles não podem simplesmente chamar o construtor da superclasse, explícita ou implicitamente, como podem em Java. Isso garante que o construtor principal seja o único ponto de entrada na 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
fonte
@ Jon McAuliffe: Mau exemplo? Sem segundo e terceiro construtores, o usuário ainda pode chamar new Foo(x=2,z=4)e new Foo(z=5)se você mudar a sua primeira linha declass Foo(x: Int = 0, y: Int = 0, z: String) {
user2987828
Argumentos nomeados / padrão não chegaram até o Scala 2.8.
21414 Jon McAuliffe
2
Vale a pena mencionar como usar um construtor de sobrecarga. Não é trivial que a newpalavra-chave seja necessária mesmo para as classes de caso.
Readren
33
 class Foo(x: Int, y: Int) {
     def this(x: Int) = this(x, 0) // default y parameter to 0
 }
Landon Kuhn
fonte
16

A partir do Scala 2.8.0, você também pode ter valores padrão para os parâmetros do contratante e do método. Como isso

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)

Parâmetros com valores padrão devem vir depois daqueles sem valores padrão na lista de parâmetros.

Jörgen Lundberg
fonte
3
Porém, isso não funciona para padrões não triviais. então class Foo(val x:Int, y:Int=2*x)não funciona.
subsub
@ Jörgen Lundberg: você escreveu Parâmetros com valores padrão devem vir depois daqueles sem valores padrão na lista de parâmetros. Está errado, new Foo(x=2,z=4)será impresso Foo(2,0,4).
user2987828
@ user2987828 o que eu quis dizer foi que você não pode escrever um novo Foo (12, x = 2), você deve escrever um novo Foo (x = 2, 12). Você pode escrever um novo Foo (12, y = 2) e obterá o Foo (12, 2, 0)
Jörgen Lundberg
10

Ao olhar para o meu código, de repente percebi que sobrecarregava um construtor. Lembrei-me da pergunta e voltei para dar outra resposta:

No Scala, você não pode sobrecarregar construtores, mas pode fazer isso com funções.

Além disso, muitos optam por tornar a applyfunção de um objeto complementar uma fábrica para a respectiva classe.

Tornando essa classe abstrata e sobrecarregando a applyfunção de implementar-instanciar essa classe, você tem seu “construtor” sobrecarregado:

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

Observe que eu defino explicitamente cada um applypara retornar Expectation[T], caso contrário, ele retornaria um tipo de pato Expectation[T]{val expected: List[T]}.

ovelha voadora
fonte
0

Tente isto

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
fonte