Перевантаження конструктора Scala?


Відповіді:


186

Варто чітко згадати, що допоміжні конструктори у Scala повинні викликати відповідь первинного конструктора (як у landon9720) або інший допоміжний конструктор того ж класу, як їх перша дія. Вони не можуть просто викликати конструктор суперкласу явно або неявно, як це можливо в Java. Це гарантує, що первинний конструктор є єдиною точкою вступу до класу.

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: Поганий приклад? Без другого та третього конструкторів користувач все ще може зателефонувати, new Foo(x=2,z=4)а new Foo(z=5)якщо змінити свою першу лінію наclass Foo(x: Int = 0, y: Int = 0, z: String) {
— user2987828

Аргументи з іменами / за замовчуванням не надходили до Scala 2.8.
— Джон МакОліфф

2
Варто було б згадати, як використовувати конструктор перевантаження. Це не банально, що newключове слово необхідне навіть для класів випадків.
— Редрен


16

На основі Scala 2.8.0 ви також можете мати значення за замовчуванням для параметрів кондуктора та методу. Подобається це

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)

Параметри зі значеннями за замовчуванням повинні відповідати значенням, у яких у списку параметрів немає значень за замовчуванням.


3
Це не працює для нетривіальних стандартних значень. тому class Foo(val x:Int, y:Int=2*x)не працює.
— підпункт

@ Йорген Лундберг: Ви писали, що Параметри зі значеннями за замовчуванням повинні відповідати тим, у яких у списку параметрів немає значення за замовчуванням. Це неправильно, new Foo(x=2,z=4)буде надруковано Foo(2,0,4).
— користувач2987828

@ user2987828, що я мав на увазі, що ви не можете написати новий Foo (12, x = 2), ви повинні написати новий Foo (x = 2, 12). Ви можете написати новий Foo (12, y = 2), тоді ви отримаєте Foo (12, 2, 0)
— Йорген Лундберг,

10

Подивившись на свій код, я раптом зрозумів, що я щось перевантажував конструктор. Потім я згадав це питання і повернувся дати ще одну відповідь:

У Scala ви не можете перевантажувати конструктори, але це можна зробити за допомогою функцій.

Також багато хто вирішує зробити applyфункцію супутнього об'єкта фабрикою для відповідного класу.

Зробивши цей клас абстрактним і перевантаживши applyфункцію для реалізації-інстанції цього класу, у вас є ваш перевантажений "конструктор":

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

Зауважте, що я чітко визначаю кожне applyповернення Expectation[T], інакше він би повертав тип-качку Expectation[T]{val expected: List[T]}.


0

Спробуйте це

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
  }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.