2013-08-12 14 views
7

Mam klasę case, która przechowuje trzy powiązane parametry. Chciałbym określić przedmiot towarzysz, który może zbudować klasę z dwoma parametrami, coś, co wygląda jak poniżej próbki, które jest oczywiście błędna:definiuje domyślne nazwane argumenty pod względem innych argumentów w scala

def test(start : Float = end - duration, duration : Float = end - start, end : Float = start + duration) { 
    require(abs(start + duration - end) < epsilon) 
    ... 
} 
val t1 = test(start = 0f, duration = 5f) 
val t2 = test(end = 4f, duration = 3f) 
val t3 = test(start = 3f, end = 5f) 

Jakie sztuczki mogę użyć, aby uzyskać podobną składnię użytkowaniu?

Odpowiedz

26

Można użyć typu klasy:

// Represents no argument 
object NoArg 

// Resolves start, duration, stop 
trait DurationRes[A,B,C] { 
    def resolve(s: A, d: B, e: C): (Float, Float, Float) 
} 

object DurationRes { 
    implicit object startEndRes extends DurationRes[Float, NoArg.type, Float] { 
    def resolve(s: Float, d: NoArg.type, e: Float) = (s, e-s, e) 
    } 
    implicit object startDurRes extends DurationRes[Float, Float, NoArg.type] { 
    def resolve(s: Float, d: Float, e: NoArg.type) = (s, d, s+d) 
    } 
    // etc. 
} 

def test[A,B,C](start: A = NoArg, dur: B = NoArg, end: C = NoArg) 
       (implicit res: DurationRes[A,B,C]) { 
    val (s,d,e) = res.resolve(start, dur, end) 
    // s is start, d duration, e end 
} 

test(start = 1f, end = 2f) 

ten sposób jest nawet typ bezpieczny i nie można nazwać coś takiego:

test(start = 1f) 

lub nawet

test() 
3

After trochę myślę, że przyszedłem z innym rozwiązaniem (nie twierdzę, że jest lepsze, po prostu chciałbym wiedzieć, czy jest to nawet akceptowalne podejście). Istotą jest zdefiniowanie klasy: class Klass(val x: Int, val y: Int, val z: Int) i obiekt towarzysz:

object Klass { 
    def apply(x: Int, y: Int)(z: Int = x + y) = { 
    new Klass(x, y, z) 
    } 
    // and so on 
} 

Więc można wtedy zrobić val k = Klass(x = 5, y = 6)() i dostać val k odnieść się do Klass(5, 6, 11) instancji.

A z powodu małej ilości kodu można prawdopodobnie zdefiniować makra do wykonania zadania, ale na razie jest to dla mnie trochę trudne, ale jest to interesujące ćwiczenie.

Aktualizacja

Po pewnym czasie, chciałbym zauważyć, że do ciebie istnieją tylko trzy kombinacje parametrów w twoim przypadku, więc nie byłoby po prostu łatwiej dostarczyć 3 apply() metod ręcznie ? apply(s, d), apply(s, e), apply(d, e) powinien wystarczyć do twoich potrzeb. To pozwoli Ci zaoszczędzić trochę pisania na klawiaturze, ponieważ w przypadku innych podejść, musisz również zakodować wszystkie te przypadki.

+0

Należy zauważyć, że działa to tylko wtedy, gdy argumenty mają różne typy. Nie można przeciążać 'apply' w ten sposób ze względu na kompatybilność z Javą. (W Javie nazwy argumentów nie są częścią interfejsu publicznego). – gzm0

Powiązane problemy