2012-02-12 20 views
7

Tôi có thể sử dụng các kỹ thuật nào trong Scala để xử lý các danh sách tham số kiểu dài?Scala: cách làm việc với danh sách tham số loại dài

Tôi đang làm việc trên một khuôn khổ nhỏ để chạy các loại trò chơi khác nhau với các môi trường mô phỏng khác nhau. Tôi đang cố giữ một số phần nhất định của khung tương đối chung chung, vì vậy tôi giới thiệu các loại khác nhau như thông số loại, chẳng hạn như trạng thái của môi trường, kết quả trò chơi, v.v.

Tất cả hoạt động khá tốt và tôi làm có được những lợi ích mong muốn của một khung công tác chung loại an toàn. Nhưng các chữ ký kiểu đã phát triển đến mức nó làm cho mã khó đọc và tái cấu trúc nó trở nên khá cồng kềnh. Chữ ký của Trình mô phỏng cấp cao nhất có tám tham số kiểu và nhiều loại chính có từ ba đến năm. Lỗi loại trình biên dịch riêng lẻ, vì chúng liệt kê ra các loại tham số lớp hoặc chức năng (tất nhiên là kiểu tham số kiểu) dường như thường xuyên chạy đến một trăm dòng.

Thỉnh thoảng, nhưng rất hiếm khi, tôi có thể bỏ qua các thông số loại, ví dụ: về các nhà thầu. Nhưng trong hầu hết các trường hợp, ít nhất một trong các loại sẽ không được suy ra nên cuối cùng tôi phải chèn toàn bộ chữ ký kiểu.

Rõ ràng đây không phải là lý tưởng và tôi đang tìm cách giải quyết vấn đề này. Lời khuyên nào sẽ được đánh giá cao!

+6

vài dòng mã mẫu luôn đánh giá cao;) – agilesteel

+0

Đó là một vấn đề rất chung chung. Tôi không chắc chắn mã mẫu sẽ thêm rất nhiều giá trị. Nó chỉ là những điều bình thường: các đặc điểm, các lớp, các hàm, với các tham số kiểu và các trường/thành viên cũng có các tham số kiểu. –

Trả lời

8

Xem xét trường hợp khi bạn có nhóm thông số loại có liên quan chặt chẽ; bạn chuyển chúng lại với nhau thành các đối số kiểu. Trong ví dụ này, nhóm này là AB.

trait X[A, B, C] { 
    new Y[A, B, Int] {} 
} 

trait Y[A, B, D] { 
    def a: A = sys.error("") 
} 

Bạn có thể gói hai loại vào một tham số kiểu duy nhất với một thành viên kiểu loại bí danh chứa:

type AB = { type A; type B } 
trait Y[ab <: AB, D] { 
    def a: ab#A = sys.error("") 
} 
trait X[ab <: AB, C] { 
    new Y[ab, C] {} 
} 
new X[{ type A=Int; type B=Int}, String] {} 
+0

Oooh, gọn gàng! Tôi sẽ cố gắng ra càng sớm càng tốt! –

+0

Bạn cũng giữ lại khả năng sử dụng phương sai với phương pháp này. – retronym

+1

Làm cách nào để chỉ định phương sai? Trong ví dụ của bạn, ví dụ: nếu Y ban đầu là Y [+ A, -B]? –

10

Hai giải pháp cần lưu ý.

  1. Sử dụng bí danh loại.

    scala> class Foo[A, B, C, D, E] 
    defined class Foo 
    
    scala> type Bar[A] = Foo[A, Int, Int, Int, Float] 
    defined type alias Bar 
    
    scala> new Bar[String] 
    res23: Foo[String,Int,Int,Int,Float] = [email protected] 
    
  2. Sử dụng abstract type members thay vì thông số loại.

    scala> class Bar { 
        | type A 
        | type B <: AnyVal 
        | type C 
        | } 
    defined class Bar 
    
    scala> new Bar { 
        | type A = String 
        | type B = Int 
        | type C = Int 
        | } 
    res24: Bar{type A = String; type B = Int; type C = Int} = [email protected] 
    
    scala> trait Baz { 
        | type A = String 
        | } 
    defined trait Baz 
    
    scala> new Bar with Baz { 
        | type B = Int 
        | type C = String 
        | } 
    res25: Bar with Baz{type B = Int; type C = String} = [email protected] 
    
    scala> null.asInstanceOf[res25.A] 
    res26: res25.A = null 
    
    scala> implicitly[res25.A =:= String] 
    res27: =:=[res25.A,String] = <function1> 
    

Bạn có thể muốn chia sẻ một số mã với chúng tôi để chúng tôi có thể đưa ra một số lời khuyên cụ thể hơn.

+0

Câu trả lời đầu tiên tôi đã sử dụng; nó thậm chí sẽ đẹp hơn nếu bằng cách nào đó bạn có thể sử dụng bí danh loại đã xác định để truy cập vào hàm tạo của kiểu cơ bản .. Thứ hai là thú vị; Tôi sẽ khám phá điều này. –

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