2012-07-09 31 views
9

Tôi đang tạo một thư viện Java, như một sản phẩm cuối cùng có ý định phân phối .jar này cho các nhà phát triển.Phạm vi và thư viện Java Class

Tôi đang "dịch" thư viện của tôi từ Objective-C nơi tôi kiểm soát các tệp tiêu đề của lớp nào có sẵn cho nhà phát triển. Nói cách khác, tôi chỉ tiếp xúc với nhà phát triển một vài lớp mà họ có thể xử lý.

Trong thư viện Java của tôi, tôi đang sử dụng các gói và gói của tôi đã phát triển khá lớn. Vì vậy, tôi quyết định tách thành các gói khác nhau các mô hình và bộ điều khiển của tôi. Nhưng bây giờ các mô hình tôi muốn giữ riêng tư tôi cần phải đánh dấu là công khai để sử dụng từ gói chính.

Câu hỏi của tôi là điều này đi ngược lại những gì tôi đã làm trong Mục tiêu-C?

Ví dụ: Tôi có lớp Sự kiện thực sự chỉ được sử dụng nội bộ và tôi không muốn người dùng biết về điều đó hoặc nghĩ về điều đó. Tôi có một lớp TimedEvent, mà người dùng có thể nhận được một thể hiện của một quản lý.

Trong Mục tiêu-C, tôi chỉ cần loại trừ lớp Sự kiện khỏi phạm vi công cộng của thư viện, cho phép TimedEvent.

Nếu tôi làm cho mọi thứ gọn gàng hơn trong thư viện của mình thì có vẻ như các gói không phải là cách. Kể từ bây giờ, bộ điều khiển chính của tôi nằm trong gói chính và tất cả các mô hình đều nằm trong một gói khác - buộc phải có phạm vi công khai.

Ý kiến?

Trả lời

5

này có thể với Java nhưng có những lý do tại sao (hầu như) không có ai làm nó ...

Nếu bạn đặt việc thực hiện và giao diện vào cùng một gói, sau đó bạn có thể bỏ qua tất cả các bổ truy cập (private , protected, public) từ các lớp và phương thức để hiển thị chúng "mặc định" hoặc "gói": Chỉ các lớp trong cùng một gói được phép xem/sử dụng chúng.

Hạn chế: Bạn sẽ phải kết hợp API và triển khai.

Cách tiếp cận khác là di chuyển việc triển khai thành gói *.private.*. Không pha trộn nhiều API và triển khai thực hiện nhưng người dùng độc hại có thể dễ dàng truy cập vào triển khai - đó chỉ là quy ước đặt tên. Giống như một dấu hiệu DỪNG: Nó có nghĩa là một cái gì đó ("cẩn thận") nhưng không thực sự ngăn cản bạn.

Cuối cùng, bạn có thể triển khai giao diện bên trong giao diện. Ví dụ:

public interface IFoo { 
    String getName(); 

    private static class Foo implements IFoo { 
     public String getName(); 
    } 

    public static class FooFactory { 
     public static IFoo create() { return new Foo(); } 
    } 
} 

Xấu hổ, phải không?

+2

Nice liên lạc về việc thực hiện bên trong giao diện. Đó có phải là một tính năng mới không? –

+1

Không, nó hoạt động vì Java hỗ trợ các lớp bên trong (1.2, tôi nghĩ) nhưng nó bổ sung thêm rất nhiều mã đĩa nồi hơi. –

+0

Rất nhiều sách giáo khoa có lỗi này. "Giao diện: hằng số và khai báo phương thức" –

4

Cách tiếp cận chung để kiểm soát việc tiếp xúc với các lớp học của bạn với thế giới là ẩn các triển khai đằng sau các giao diện và nhà máy.

  • Tạo một giao diện cho TimedEvent của bạn, và một lớp để tạo các trường hợp TimedEvent giao diện
  • Đặt giao diện trong gói chính, và các nhà máy ở một tiểu gói
  • Cho khả năng hiển thị công nhà máy
  • Triển khai giao diện trong gói phụ, giúp hiển thị gói
  • Tạo một thể hiện của lớp triển khai giao diện TimedEvent trong nhà máy

Dưới đây là một ví dụ về cách bạn có thể làm điều đó:

package com.my.main; 
public interface TimedEvent { 
    void fire(); 
} 

package com.my.main.events; 
import com.my.main; 
public class EventFactory { 
    public TimedEvent makeTimedEvent() { return new TimedEvent(); } 
} 
// TimedEventImpl has package visibility - it is not public. 
class TimedEventImpl implements TimedEvent { 
    public void fire() { 
     // Fire a timed event 
    } 
} 

Người sử dụng sẽ truy cập TimedEvent như thế này:

com.my.main.events.EventFactory f = new com.my.main.events.EventFactory(); 
com.my.main.TimedEvent evt = f.makeTimedEvent(); 
evt.fire();