web-dev-qa-db-ja.com

Javaの一部のクラスに対して一部のメソッドを非表示/使用不可にすることは可能ですか?

Javaでアプリケーションを開発しています。これにより、オブジェクトをインターフェイスの一部として、チームの他の開発者が作成したクラスの他のメソッドに渡したいと思います。渡しているオブジェクトは通常の方法でセッターとゲッターを渡しますが、渡されたオブジェクトのセッターの一部に他のユーザーが作成したクラスにアクセスさせたくありません(オブジェクトを使用するときに、クラスごとに異なるセッターを使用できます)。これは可能ですか? Javaで?すなわち、どのクラスが他のクラスのどのメソッドをクラスごとに使用できるかを定義する?

私がしたいのは次のようなものだと思います:

someObject.method(passInObject[but don't give access to passInObject.thisSetter])

ここで、「someObject」はチームメンバーによって記述されたクラスのオブジェクトであり、「passInObject」は私のクラスのオブジェクトですが、この特定のsomeObjectクラスからそのメンバーの一部を保護したいと思います。

私はそうではないと思います、他の特定のモジュールに使用/表示させたくないセッターをオーバーライドするために継承を使用する必要がありますが、一部の内部値のみを保護することに基づいて、使用中のクラスごとに新しい継承クラスを作成するのは不格好です一部はクラスを使用しています。メンバーの値が変更されていないことをコードで確認することはできますが、それでは遅すぎて損傷が発生します(元に戻すのはコストがかかる可能性があります)。クラスの名前をセッターメソッド自体で確認し、名前が「禁止」リストにある場合は何もできませんが、これは非常に不格好でエラーが発生しやすいようです。必要なのは、渡されたオブジェクトで呼び出すことができるメンバーを制限する呼び出しコードです。

それとも私は何かを逃していて、これを処理するための一般的なパターンがありますか?

2

それはできません。あなたの問題は、 [〜#〜] isp [〜#〜] の違反から発生します。

そうは言っても、私が考えることができる唯一のアイデアは、クライアントクラスを強制的にordenのクラスに登録して、それらのメソッドを呼び出せるようにするか、NotRegisteredExceptionを取得できるようにすることです。登録したら、タイプを確認し、登録されたクラスが許可されたクラスのリストにない場合はYouAreNotAllowedToCallThisMethodExceptionを上げることができます。

これは非常に洗練されていない解決策であり、インターフェイスを分離することでISP違反を修正したいと思います。しかし、それによって同僚が使用したくないインターフェイスを同僚が使用できなくなるわけではありません。

次のコード例は、別の質問からの this great answer by user Marjan Venema からのものです。

interface IEverythingButTheKitchenSink
{
     void DoDishes();
     void CleanSink();
     void CutGreens();
     void GrillMeat();
}

interface IClean
{
     void DoDishes();
     void CleanSink();
}

interface ICook
{
     void CutGreens();
     void GrillMeat();
}
8

継承されたメソッドを隠すことはひどい考えであり、悲しみを引き起こすことはほぼ確実です。

これがInterfacesの目的です。 2つ以上のクラス間の「開示契約」。各クラスが他のクラスについて知ることを許可されている内容を正確に説明します。

もちろん、そのmixedが継承と一緒に記述されている場合、基本クラスがインターフェイスを実装する場合、または各派生クラスが実装する場合それ自体で? YMMV。

5
Phill W.

あなたが望むことを正確に行うことはできません-他の答えを見てください、しかしあなたができることがいくつかあります。

  1. セッターを公開するパッケージプライベートインターフェイスと、ゲッターを公開するパブリックインターフェイスを使用できます。
    • あなたは自分のコードの複数のパッケージでセッターを使用したいと述べています。どうしてこれなの?これは私にとってコードの匂いです-あなたのコードが、クラスが定義されているパッケージの外のクラスの内部動作を混乱させる可能性がある場合、あなたは breaking encapsulation のように聞こえ、リファクタリングを検討する必要があります。
  2. これらのクラスの不変のスナップショットをリリースするビルダー/ファクトリーオブジェクトを使用できます。
    • これはpreferredアプローチであり、特にアプリケーションがマルチスレッドコードを使用している場合は特にそうです。元のクラスのすべてのデータを含む [〜#〜] pojo [〜#〜] を作成すると、必要な安全性が追加され、コードが作成されます後でデバッグする方がはるかに簡単です。

何をするにせよ、特にパッケージの外で、共有オブジェクトが変化する可能性がある状況を制限することにいくらかのエネルギーを費やすことは、この問題に対処するのに役立ち、コードを後で簡単に維持できるようにします。


参考文献:

2
durron597

特定のシナリオに応じて、Javaでそれを行うには多くの方法があります。

一方では、このシナリオでアクセス修飾子が役立つかどうかの分析を開始できます。

たとえば、Javaでは、パッケージを使用してコードをモジュール化できます。

_package a;

public class A {
   private String foo;
   public String getFoo(){ return this.foo; }
   void setFoo(String foo){ this.foo = foo; }
}
_

上記のコードでは、パッケージレベルのアクセスで定義されているため、パッケージAのクラスだけがメソッドsetFooへのアクセスを許可されますが、パブリックであるため、誰でもgetFoo()を呼び出すことができます。 。

クラスのユーザーが別のパッケージ(最も一般的なシナリオ)に含まれていることがわかっている場合は、これが完全に機能します。パッケージを使用して凝集モジュールを定義し、公開したいものだけを公開します。

独自のパッケージのメンバーの機能を非表示にしたい場合は、デザインに問題がある可能性があるため、サブパッケージが必要になるか、他の回答で提案されているより多くのインターフェイスを使用する可能性があります。

0
edalorzo

あなたの間違いがアクセスに対して細かすぎるアプローチを取っている可能性があります。クラスの各ユーザーが異なるアクセス権を持つことを確信していますか?おそらく、実際の問題は、特定のロールを持つユーザーのみが特定のメソッドにアクセスできるRoleメカニズムを実装する必要があることです。

Roleメカニズムは、さまざまなインターフェースを使用して実装することも、 Proxy を使用して実際のきめ細かい制御を実装することもできます。

0
OldCurmudgeon