Перевантаження конструктора 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.