2013-08-12 31 views
7

Tôi có một lớp chữ thường chứa ba thông số được gắn. Tôi muốn xác định đối tượng đồng có thể xây dựng các lớp học từ bất kỳ hai tham số, cái gì đó trông giống như các mẫu dưới đây, mà rõ ràng là không đúng:xác định các đối số được đặt tên mặc định theo các đối số khác trong 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) 

gì thủ đoạn tôi có thể sử dụng để có được cú pháp sử dụng tương tự?

Trả lời

26

Bạn có thể sử dụng loại-lớp:

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

Bằng cách này nó thậm chí còn gõ an toàn và bạn không thể gọi cái gì đó như:

test(start = 1f) 

hoặc thậm chí

test() 
3

Sau một chút suy nghĩ tôi đã đi với một giải pháp khác (tôi không tuyên bố nó tốt hơn, chỉ muốn biết nếu nó là phương pháp tiếp cận chấp nhận được). Điều cốt lõi là xác định một lớp: class Klass(val x: Int, val y: Int, val z: Int) và một đối tượng đồng:

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

Vì vậy, bạn có thể làm val k = Klass(x = 5, y = 6)() và nhận val k để chỉ Klass(5, 6, 11) dụ.

Và vì số lượng mã nhỏ, người ta có thể xác định một macro để thực hiện công việc, nhưng đó là một chút khó khăn đối với tôi như hiện tại, nhưng là một bài tập thú vị.

Cập nhật

Sau một thời gian, tôi muốn lưu ý với bạn rằng chỉ có ba sự kết hợp của các thông số trong trường hợp của bạn, vì vậy nó sẽ không được dễ dàng hơn để cung cấp 3 phương pháp apply() bằng tay ? apply(s, d), apply(s, e), apply(d, e) đủ nhu cầu của bạn. Và điều đó sẽ giúp bạn tiết kiệm một số cách gõ, bởi vì với các cách tiếp cận khác, về cơ bản bạn phải mã hóa tất cả các trường hợp đó.

+0

Lưu ý rằng thao tác này chỉ hoạt động nếu đối số của bạn có các loại khác nhau. Bạn không thể quá tải 'áp dụng' như thế này do khả năng tương thích với Java. (Trong Java, các tên đối số không phải là một phần của giao diện công cộng). – gzm0

Các vấn đề liên quan