2010-08-03 35 views
75

Đối tượng gói là gì, không quá nhiều khái niệm nhưng cách sử dụng chúng?Đối tượng đóng gói

tôi đã cố gắng để có được một ví dụ làm việc và hình thức duy nhất mà tôi đã đến làm việc là như sau:

package object investigations { 
    val PackageObjectVal = "A package object val" 
} 

package investigations { 

    object PackageObjectTest { 
     def main(args: Array[String]) { 
      println("Referencing a package object val: " + PackageObjectVal) 
     } 
    } 
} 

quan sát tôi đã thực hiện cho đến nay là:

package object _root_ { ... } 

là không được phép (điều này là hợp lý),

package object x.y { ... } 

cũng không được phép.

Dường như đối tượng gói phải được khai báo trong gói mẹ ngay lập tức và nếu được viết như trên, thì cần phải có mẫu khai báo gói được giới hạn cú đúp.

Chúng có được sử dụng phổ biến không? Nếu vậy, làm thế nào?

+6

http://www.naildrivin5.com/scalatour/wiki_pages/PackageObjects – oluies

+1

@Brent, đây là một tài nguyên tuyệt vời, không chỉ cho bài viết đối tượng gói. Tôi đã nghe về tác giả nhưng không nhận ra anh ấy đã viết tour du lịch Scala này, cảm ơn. –

Trả lời

113

Thông thường bạn sẽ đặt đối tượng gói trong một file riêng biệt gọi là package.scala trong gói mà nó tương ứng với. Bạn cũng có thể sử dụng cú pháp gói lồng nhau nhưng điều đó khá bất thường.

Trường hợp sử dụng chính cho các đối tượng gói là khi bạn cần định nghĩa ở các vị trí khác nhau bên trong gói của bạn cũng như bên ngoài gói khi bạn sử dụng API được xác định bởi gói. Dưới đây là ví dụ:

// file: foo/bar/package.scala 

package foo 

package object bar { 

    // package wide constants: 
    def BarVersionString = "1.0" 

    // or type aliases 
    type StringMap[+T] = Map[String,T] 

    // can be used to emulate a package wide import 
    // especially useful when wrapping a Java API 
    type DateTime = org.joda.time.DateTime 

    type JList[T] = java.util.List[T] 

    // Define implicits needed to effectively use your API: 
    implicit def a2b(a: A): B = // ... 

} 

Bây giờ các định nghĩa bên trong đối tượng gói đó có sẵn trong toàn bộ gói foo.bar. Hơn nữa các định nghĩa được nhập khẩu khi ai đó bên ngoài gói đó nhập foo.bar._.

Bằng cách này, bạn có thể ngăn yêu cầu ứng dụng API đưa ra các nhập bổ sung để sử dụng thư viện của bạn một cách hiệu quả - ví dụ: trong scala-đu bạn cần phải viết

import swing._ 
import Swing._ 

để có tất cả sự tốt lành như onEDT và chuyển đổi ngầm Tuple2-Dimension.

+12

Cảnh báo: quá tải phương thức không hoạt động trong các đối tượng gói. – retronym

+0

Đánh bại tôi lý do tại sao nó đã được chọn rằng các đối tượng gói nên được xác định một cấp lên hệ thống phân cấp gói. Ví dụ. điều này có nghĩa là bạn cần phải gây ô nhiễm gói cấp cao nhất 'org' hoặc' com' ảo với đối tượng gói của mình nếu bạn muốn nó thuộc về gói gốc của chính bạn, ví dụ: 'org.foo'. Tôi thấy rằng cho phép định nghĩa được trực tiếp dưới gói nó phải là một phần của - sẽ có giao diện api ngôn ngữ thích hợp hơn một chút. – matanster

7
+0

@Alex Cruise, cảm ơn, điều này dường như gợi ý rằng họ cần một đơn vị biên dịch riêng biệt (có lẽ là vòng giới hạn gói được giới hạn bằng dấu ngoặc nhọn). Vấn đề là tôi muốn một số lời khuyên người dùng vững chắc hơn là phỏng đoán của riêng tôi về cách sử dụng chúng. –

51

Trong khi câu trả lời của Moritz là tại chỗ, một điều bổ sung cần lưu ý là đối tượng gói là đối tượng. Trong số những thứ khác, điều này có nghĩa là bạn có thể xây dựng chúng từ những đặc điểm, sử dụng di sản hỗn hợp. Ví dụ Moritz của có thể được viết như

package object bar extends Versioning 
          with JodaAliases 
          with JavaAliases { 

    // package wide constants: 
    override val version = "1.0" 

    // or type aliases 
    type StringMap[+T] = Map[String,T] 

    // Define implicits needed to effectively use your API: 
    implicit def a2b(a: A): B = // ... 

} 

Đây Versioning là một đặc điểm trừu tượng, mà nói rằng đối tượng gói phải có một "phiên bản" phương pháp, trong khi JodaAliases và JavaAliases là những đặc điểm cụ thể chứa bí danh kiểu tiện dụng. Tất cả những đặc điểm này có thể được tái sử dụng bởi nhiều đối tượng gói khác nhau.

+0

Toàn bộ chủ đề đang mở ra rất nhiều và dường như nó được sử dụng để có tiềm năng đầy đủ, nhờ một ví dụ phong phú khác. –

+1

nhưng chúng không thể được sử dụng làm vals, vì vậy chúng không thực sự là đối tượng –

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