2009-12-27 36 views
108

Tôi có hai gói trong dự án của tôi: odp.projodp.proj.test. Có một số phương pháp mà tôi muốn được hiển thị chỉ cho các lớp trong hai gói này. Tôi có thể làm cái này như thế nào?Java: Khả năng hiển thị subpackage?

EDIT: Nếu không có khái niệm về gói phụ trong Java, có cách nào xung quanh vấn đề này không? Tôi có một số phương pháp mà tôi muốn chỉ có sẵn cho người thử nghiệm và các thành viên khác của gói đó. Tôi có nên ném mọi thứ vào cùng một gói không? Sử dụng phản chiếu rộng rãi?

+0

http://stackoverflow.com/questions/2388253/separation-of-junit-classes-into-special-test-package – Abdull

+0

http://stackoverflow.com/questions/13809713/java-package-in-package –

+1

Ngoài ra, các xét nghiệm chỉ nên kiểm tra * hành vi * của các đối tượng của bạn như có thể quan sát được từ bên ngoài gói. Việc truy cập các phương thức/lớp phạm vi gói từ các thử nghiệm của bạn cho tôi biết các bài kiểm tra có lẽ là việc thử nghiệm các triển khai không phải là các hành vi. Sử dụng công cụ xây dựng như maven hoặc gradle, chúng sẽ giúp bạn dễ dàng chạy thử trong cùng một classpath nhưng không được bao gồm trong jar cuối cùng (một điều tốt), do đó không cần chúng có tên gói khác nhau. Tuy nhiên, đặt chúng trong các gói riêng biệt anyways * là bắt buộc bạn không truy cập vào phạm vi riêng/mặc định * và do đó chỉ kiểm tra api công khai. – derekv

Trả lời

126

Bạn không thể. Trong Java không có khái niệm về một gói con, vì vậy odp.proj và odp.proj.test là các gói hoàn toàn riêng biệt.

+3

Mặc dù tôi thích nó theo cách này, nó gây nhầm lẫn rằng hầu hết các IDE đặt các gói có cùng tên với nhau. Cảm ơn bạn đã làm rõ. – JacksOnF1re

11

Đây không phải là mối quan hệ đặc biệt giữa odp.projodp.proj.test - chúng chỉ xảy ra được đặt tên có vẻ như có liên quan.

Nếu gói odp.proj.test chỉ đơn giản là cung cấp các kiểm tra thì bạn có thể sử dụng cùng tên gói (odp.proj). Các IDE như Eclipse và Netbeans sẽ tạo các thư mục riêng biệt (src/main/java/odp/projsrc/test/java/odp/proj) với cùng tên gói nhưng với ngữ nghĩa JUnit.

Lưu ý rằng các IDE này sẽ tạo thử nghiệm cho các phương thức trong odp.proj và tạo thư mục thích hợp cho các phương pháp thử nghiệm không tồn tại.

50

Tên của các gói của bạn gợi ý rằng ứng dụng ở đây là để kiểm tra đơn vị. Mẫu điển hình được sử dụng là đặt các lớp bạn muốn kiểm tra và mã kiểm tra đơn vị trong cùng một gói (trong trường hợp của bạn là odp.proj) nhưng trong các cây nguồn khác nhau. Vì vậy, bạn sẽ đặt các lớp học của mình vào src/odp/proj và mã kiểm tra của bạn trong test/odp/proj.

Java không có công cụ sửa đổi truy cập "gói" là công cụ sửa đổi truy cập mặc định khi không được chỉ định (nghĩa là bạn không chỉ định công khai, riêng tư hoặc được bảo vệ). Với bộ sửa đổi truy cập "gói", chỉ các lớp trong odp.proj mới có quyền truy cập vào các phương thức. Nhưng hãy nhớ rằng trong Java, các công cụ sửa đổi truy cập không thể dựa vào để thực thi các quy tắc truy cập bởi vì với sự phản chiếu, mọi truy cập đều có thể. Access modifiers chỉ đơn thuần là gợi ý (trừ khi có một trình quản lý bảo mật hạn chế).

0

Nếu không đặt công cụ sửa đổi truy cập ở phía trước phương thức bạn nói rằng nó là gói riêng tư.
Hãy xem ví dụ sau.

package odp.proj; 
public class A 
{ 
    void launchA() { } 
} 

package odp.proj.test; 
public class B 
{ 
    void launchB() { } 
} 

public class Test 
{ 
    public void test() 
    { 
     A a = new A(); 
     a.launchA() // cannot call launchA because it is not visible 
    } 
} 
1

EDIT: Nếu không có khái niệm về một gói con trong Java, có cách nào xung quanh này? Tôi có một số phương thức nhất định mà tôi muốn chỉ có sẵn cho người kiểm tra và các thành viên khác trong gói đó .

Nó có thể phụ thuộc một chút vào động cơ của bạn không hiển thị chúng, nhưng nếu lý do duy nhất là bạn không muốn gây ô nhiễm giao diện công cộng với những thứ chỉ dành cho thử nghiệm (hoặc một số nội bộ khác) sẽ đặt các phương thức trong một giao diện công cộng riêng biệt và có người tiêu dùng các phương thức "ẩn" sử dụng giao diện đó. Nó sẽ không ngăn chặn người khác sử dụng giao diện nhưng tôi không thấy lý do tại sao bạn nên.

Đối với các bài kiểm tra đơn vị và nếu có thể mà không cần viết lại lô, hãy làm theo các đề xuất để sử dụng cùng một gói.

5

Khi tôi làm điều này trong IntelliJ, cây nguồn của tôi trông như thế này:

src   // source root 
- odp 
    - proj // .java source here 
- test  // test root 
    - odp 
    - proj // JUnit or TestNG source here 
0

Với lớp PackageVisibleHelper, và giữ riêng tư trước khi PackageVisibleHelperFactory đông lạnh, chúng ta có thể gọi launchA (bởi PackageVisibleHelper) phương pháp trong bất cứ nơi nào :)

package odp.proj; 
public class A 
{ 
    void launchA() { } 
} 

public class PackageVisibleHelper { 

    private final PackageVisibleHelperFactory factory; 

    public PackageVisibleHelper(PackageVisibleHelperFactory factory) { 
     super(); 
     this.factory = factory; 
    } 

    public void launchA(A a) { 
     if (factory == PackageVisibleHelperFactory.INSTNACNE && !factory.isSampleHelper(this)) { 
      throw new IllegalAccessError("wrong PackageVisibleHelper "); 
     } 
     a.launchA(); 
    } 
} 


public class PackageVisibleHelperFactory { 

    public static final PackageVisibleHelperFactory INSTNACNE = new PackageVisibleHelperFactory(); 

    private static final PackageVisibleHelper HELPER = new PackageVisibleHelper(INSTNACNE); 

    private PackageVisibleHelperFactory() { 
     super(); 
    } 

    private boolean frozened; 

    public PackageVisibleHelper getHelperBeforeFrozen() { 
     if (frozened) { 
      throw new IllegalAccessError("please invoke before frozen!"); 
     } 
     return HELPER; 
    } 

    public void frozen() { 
     frozened = true; 
    } 

    public boolean isSampleHelper(PackageVisibleHelper helper) { 
     return HELPER.equals(helper); 
    } 
} 
package odp.proj.test; 

import odp.proj.A; 
import odp.proj.PackageVisibleHelper; 
import odp.proj.PackageVisibleHelperFactory; 

public class Test { 

    public static void main(String[] args) { 

     final PackageVisibleHelper helper = PackageVisibleHelperFactory.INSTNACNE.getHelperBeforeFrozen(); 
     PackageVisibleHelperFactory.INSTNACNE.frozen(); 


     A a = new A(); 
     helper.launchA(a); 

     // illegal access  
     new PackageVisibleHelper(PackageVisibleHelperFactory.INSTNACNE).launchA(a); 
    } 
} 
0

Như những người khác đã giải thích, không có thứ như "gói phụ" trong Java: tất cả các gói đều bị cô lập và không thừa hưởng gì từ cha mẹ.

Cách dễ dàng để truy cập thành viên lớp được bảo vệ từ gói khác là mở rộng lớp và ghi đè lên các thành viên.

Ví dụ, để truy cập ClassInA trong gói a.b:

package a; 

public class ClassInA{ 
    private final String data; 

    public ClassInA(String data){ this.data = data; } 

    public String getData(){ return data; } 

    protected byte[] getDataAsBytes(){ return data.getBytes(); } 

    protected char[] getDataAsChars(){ return data.toCharArray(); } 
} 

làm cho một lớp trong gói đó sẽ ghi đè các phương pháp bạn cần trong ClassInA:

package a.b; 

import a.ClassInA; 

public class ClassInAInB extends ClassInA{ 
    ClassInAInB(String data){ super(data); } 

    @Override 
    protected byte[] getDataAsBytes(){ return super.getDataAsBytes(); } 
} 

đó cho phép bạn sử dụng lớp trọng thay cho lớp học trong gói khác:

package a.b; 

import java.util.Arrays; 

import a.ClassInA; 

public class Driver{ 
    public static void main(String[] args){ 
     ClassInA classInA = new ClassInA("string"); 
     System.out.println(classInA.getData()); 
     // Will fail: getDataAsBytes() has protected access in a.ClassInA 
     System.out.println(Arrays.toString(classInA.getDataAsBytes())); 

     ClassInAInB classInAInB = new ClassInAInB("string"); 
     System.out.println(classInAInB.getData()); 
     // Works: getDataAsBytes() is now accessible 
     System.out.println(Arrays.toString(classInAInB.getDataAsBytes())); 
    } 
} 

Lưu ý rằng thao tác này chỉ hoạt động đối với các thành viên được bảo vệ, có thể hiển thị để mở rộng các lớp và không phải là thành viên riêng tư của gói. Hy vọng rằng điều này sẽ giúp một ai đó!

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