静的ステートマシンに、アプリケーションが最初に起動されたときに1回だけ使用されるメソッドがあります。メソッドは公開する必要がありますが、それでも非表示にします。プロジェクトの残りの部分からメソッドを隠すアノテーションまたは何かを使用する方法はありますか?
10 に答える
パブリックメソッドを非表示にすることはできません(プライベートとして宣言できない場合)。ただし、サブクラスを配置して、オブジェクトのユーザーにのみスーパークラスのタイプを知らせることができます。つまり、次のようになります。
class A {
//Externally visible members
}
class B extends A {
//Secret public members
}
次に、クラスBをインスタンス化しますが、タイプAだけを他の人に知らせます...
public methodを宣言すると、それはクラスのコントラクトの一部になります。すべてのクラスユーザーがこのメソッドが使用可能であることを期待するため、非表示にすることはできません。
publicの代わりにパッケージレベルを使用できます。そうすれば、アプリケーションからのみ呼び出すことができます。
メソッドがパブリックの場合、非表示にすることはできません。あなたが本当に探しているのは、メソッドの呼び出しへのアクセスを制限する方法にすぎません。同様の効果を達成する他の方法があります。
ステートマシンが実行する「アプリケーションが最初に起動されたときに1回だけ使用される」ことがある場合、それらはコンストラクターで発生する可能性があることとよく似ています。これらのタスクがどれほど複雑かにもよりますが、構築時にそれを実行したくない場合があります。
ステートマシンは静的であるとおっしゃっていましたが、シングルトンでもありますか?シングルトンパターンを使用できます。
public class SimpleStateMachine {
private static SimpleStateMachine instance = new SimpleStateMachine();
private SimpleStateMachine() {
super();
System.out.println("Welcome to the machine"); // prints 1st
}
public static SimpleStateMachine getInstance() {
return instance;
}
public void doUsefulThings() {
System.out.println("Doing useful things"); // prints 3rd
}
}
このシングルトンのクライアントのコードは次のとおりです。
public class MachineCaller {
static SimpleStateMachine machine = SimpleStateMachine.getInstance();
public static void main(String... args) {
System.out.println("Start at the very beginning"); // prints 2nd
machine.doUsefulThings();
}
}
SimpleStateMachine
クラスに最初にアクセスするまで、インスタンスはビルドされないことに注意してください。クライアントで宣言されているため、これstatic
はMachineCaller
「最初のアクセス」としてカウントされ、インスタンスが作成されます。アプリケーションの起動時にステートマシンでこれらの初期化タスクの一部を確実に実行する場合は、この点に注意してください。
したがって、ステートマシンクラスを真のシングルトンに変えたくない場合は、静的初期化ブロックを使用して、クラスに初めてアクセスしたときに1回限りのタスクを実行できます。これは次のようになります。
public class SimpleStateMachine {
static {
System.out.println("First time tasks #1");
System.out.println("First time tasks #2");
}
public SimpleStateMachine() {
super();
System.out.println("Welcome to the machine");
}
public void doUsefulThings() {
System.out.println("Doing useful things");
}
}
私たちがそれに取り組んでいる間、あなたはそれがステートマシンだと言ったので... Head First Design Patternsの本は、ステートパターンの素晴らしくて簡単に理解できる扱いをします。まだ読んでいない場合は、読むことをお勧めします。
これを行うための慣用的なアプローチは、インターフェースを使用してメソッドの可視性を制限することです。
たとえば、次のクラスがあるとします。
public class MyClass {
public void method1() {
// ...
}
public void method2() {
// ...
}
}
プロジェクトの一部を表示のみに制限したい場合method1()
は、インターフェースでそれを記述し、クラスにそのインターフェースを実装させることです。
public interface Method1Interface {
public void method1();
}
...
public class MyClass implements Method1Interface {
public void method1() {
// ...
}
public void method2() {
// ...
}
}
MyClass
次に、参照として、または参照としてクラスを渡すことを選択することにより、メソッドの可視性を制限できますMethod1Interface
。
public class OtherClass {
public void otherMethod1(MyClass obj) {
// can access both obj.method1() and obj.method2()
}
public void otherMethod2(Method1Interface obj) {
// can only access obj.method1(), obj.method2() is hidden.
}
}
このアプローチの利点は、簡単に拡張できることです。たとえば、へのアクセスを個別に制御したいとしますmethod2()
。必要なのはMethod2Interface
、と同じ行に沿って新しいものを作成しMethod1Interface
、それをMyClass
実装することだけです。method2()
次に、とまったく同じ方法でへのアクセスを制御できますmethod1()
。
これは、 @ MathiasSchwarzの回答で提唱されているアプローチと似ていますが、はるかに柔軟です。
- 前の段落で説明した独立したアクセス制御は、Javaが多重継承をサポートしていないため、Mathiasの手法では不可能です。
- 継承関係を必要としないことで、クラス階層をより柔軟に設計することもできます。
- 元のクラスに必要な唯一の変更は、を追加することです。これは、の既存のユーザーをまったく変更する必要がないため(少なくとも、使用するように変更することを選択するまで)、影響が非常に少ないリファクタリング
implements Method1Interface
であることを意味します。 )。MyClass
Method1Interface
別の解決策:それを作成し、リフレクションを使用しprivate
てメソッドを作成できます。invokeHiddenMethod(String methodName, Object ... args)
うーん...プライベートメソッドが必要ですが、外部からアクセスしたいですか?
リフレクションでこれを試してください。 http://download.oracle.com/javase/tutorial/reflect/index.html
パブリックメソッドは、アプリケーションの起動時に1回だけ使用されるとおっしゃいました。
おそらく、メソッドを公開したままにして、最初の呼び出しの後で何もしないようにすることはできますか?
(非)キーワードレベルのパッケージレベルの可視性があります。パブリック、保護、またはプライベートの代わりに、何も使用しません。
これにより、メソッドまたはクラスがパッケージ内のクラスや他のユーザーに表示されますが、ある程度のプライバシーが確保されます。Javaでのパッケージレベルの保護の使用とは何ですか?。
私は多くのJavaプログラマーがこのようなことをするのを見てきました:
public static void main(String args[]) {
new MyClass();
}
つまり、基本的には、クラスのオブジェクトを1つだけ作成します。一度だけ実行する必要があるメソッドがある場合、このアプローチでそれを達成できると思います。メソッドはコンストラクター内から呼び出されます。しかし、あなたのアプリがどのように機能するのかわからないので、制約は何ですか、それは単なる考えです。