Jak zapewnić przeciążone konstruktory w Scali?
Jak zapewnić przeciążone konstruktory w Scali?
Odpowiedzi:
Warto wyraźnie wspomnieć, że konstruktory pomocnicze w Scali muszą albo wywołać odpowiedź głównego konstruktora (jak w landon9720), albo innego pomocniczego konstruktora z tej samej klasy, jako swoją pierwszą akcję. Nie mogą po prostu wywołać konstruktora nadklasy jawnie lub niejawnie, tak jak w Javie. Zapewnia to, że główny konstruktor jest jedynym punktem wejścia do klasy.
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);
}
new
słowo kluczowe jest konieczne nawet w przypadku klas przypadków.
class Foo(x: Int, y: Int) {
def this(x: Int) = this(x, 0) // default y parameter to 0
}
Począwszy od Scala 2.8.0 możesz również mieć domyślne wartości parametrów contructor- i method. Lubię to
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)
Parametry z wartościami domyślnymi muszą występować po parametrach bez wartości domyślnych na liście parametrów.
class Foo(val x:Int, y:Int=2*x)
nie działa.
new Foo(x=2,z=4)
wydrukuje Foo(2,0,4)
.
Patrząc na mój kod, nagle zdałem sobie sprawę, że trochę przeładowałem konstruktora. Potem przypomniałem sobie to pytanie i wróciłem, aby udzielić innej odpowiedzi:
W Scali nie możesz przeciążać konstruktorów, ale możesz to zrobić za pomocą funkcji.
Wiele osób decyduje się również na uczynienie apply
funkcji obiektu towarzyszącego fabryką dla odpowiedniej klasy.
Uczyniając tę klasę abstrakcyjną i przeciążając apply
funkcję w celu zaimplementowania tej klasy, otrzymujesz przeciążony „konstruktor”:
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)
…
}
}
Zauważ, że jawnie definiuję każdy apply
z nich do zwrotu Expectation[T]
, w przeciwnym razie zwróciłoby to kaczkę wpisaną Expectation[T]{val expected: List[T]}
.
Spróbuj tego
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
}
}
new Foo(x=2,z=4)
inew Foo(z=5)
jeśli zmienisz pierwszą linię naclass Foo(x: Int = 0, y: Int = 0, z: String) {