プロジェクトに2つのパッケージがあります:odp.proj
およびodp.proj.test
。これら2つのパッケージのクラスにのみ表示したい特定のメソッドがあります。これどうやってするの?
編集: Javaにサブパッケージの概念がない場合、これを回避する方法はありますか?テスターとそのパッケージの他のメンバーだけが利用できるようにする特定のメソッドがあります。すべてを同じパッケージに入れる必要がありますか?広範な反射を使用しますか?
できません。 Javaではサブパッケージの概念がないため、odp.projとodp.proj.testは完全に別個のパッケージです。
パッケージの名前は、ここでのアプリケーションが単体テスト用であることを示唆しています。使用される典型的なパターンは、テストするクラスとユニットテストコードを同じパッケージ(場合によってはodp.proj
)に、ただし異なるソースツリーに配置することです。したがって、クラスをsrc/odp/proj
に、テストコードをtest/odp/proj
に配置します。
Javaには、「パッケージ」アクセス修飾子があります。これは、何も指定されていない場合(つまり、public、private、またはprotectedを指定しない場合)のデフォルトのアクセス修飾子です。 「パッケージ」アクセス修飾子を使用すると、odp.proj
のクラスのみがメソッドにアクセスできます。ただし、Javaでは、リフレクションを使用するとすべてのアクセスが可能になるため、アクセスルールを適用するためにアクセス修飾子を使用することはできません。アクセス修飾子は示唆的なものにすぎません(制限的なセキュリティマネージャーが存在しない場合)。
これはodp.proj
とodp.proj.test
の間の特別な関係ではありません-それらはたまたま明らかに関連していると命名されています。
Odp.proj.testパッケージが単にテストを提供している場合、同じパッケージ名(odp.proj
)を使用できます。 EclipseやNetbeansなどのIDEは、同じパッケージ名でJUnitセマンティクスを使用して、個別のフォルダー(src/main/Java/odp/proj
およびsrc/test/Java/odp/proj
)を作成します。
これらのIDEはodp.proj
のメソッドのテストを生成し、存在しないテストメソッドに適切なフォルダーを作成することに注意してください。
IntelliJでこれを行うと、ソースツリーは次のようになります。
src // source root
- odp
- proj // .Java source here
- test // test root
- odp
- proj // JUnit or TestNG source here
編集:Javaにサブパッケージの概念がない場合、これを回避する方法はありますか?テスターとそのパッケージの他のメンバーだけが利用できるようにする特定のメソッドがあります。
それらを表示しない動機におそらく依存しますが、唯一の理由が、パブリックインターフェイスをテストのみを目的とするもの(または他の内部のもの)で汚染したくない場合である場合、メソッドを個別のパブリックインターフェイスを作成し、「非表示」メソッドのコンシューマーにそのインターフェイスを使用させます。他の人がインターフェースを使用するのを止めることはありませんが、なぜそうすべきなのか分かりません。
単体テストの場合、およびロットを書き換えなくても可能であれば、同じパッケージを使用するための提案に従ってください。
他の人が説明したように、Javaには「サブパッケージ」のようなものはありません。すべてのパッケージは分離され、親から何も継承しません。
別のパッケージから保護されたクラスメンバーにアクセスする簡単な方法は、クラスを拡張し、メンバーをオーバーライドすることです。
たとえば、パッケージa.b
のClassInA
にアクセスするには:
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(); }
}
ClassInA
で必要なメソッドをオーバーライドするクラスをそのパッケージに作成します。
package a.b;
import a.ClassInA;
public class ClassInAInB extends ClassInA{
ClassInAInB(String data){ super(data); }
@Override
protected byte[] getDataAsBytes(){ return super.getDataAsBytes(); }
}
これにより、他のパッケージのクラスの代わりにオーバーライドクラスを使用できます。
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()));
}
}
これは、拡張クラス(継承)に表示される保護されたメンバーに対してのみ機能し、同じパッケージ内のサブ/拡張クラスにのみ表示されるパッケージプライベートメンバーには機能しないことに注意してください。これが誰かの助けになることを願っています!
PackageVisibleHelperクラスを使用し、PackageVisibleHelperFactoryを凍結する前にプライベートにしておくと、launchA(by PackageVisibleHelper)メソッドをどこでも呼び出すことができます:)
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);
}
}
メソッドの前にアクセス修飾子を配置せずに、それがパッケージプライベートであると言います。
次の例をご覧ください。
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
}
}