2011-12-05 6 views
1

最初に、明確化:「インターフェース」とは、必ずしもコンポーネントの相互作用のポイントを意味し、必ずしも「抽象タイプ」のインターフェースの種類ではない。 (私はこのようなインターフェイスを使用することができますが、これは素晴らしいです。)別のクラスでプライベート変数にアクセスできるようにするインターフェイスを提供できますか?

私は拡張するように設計されたクラスを書いています。問題のドメインはグローバルな最適化です。つまり、自分のクラスをサブクラス化するエンドユーザプログラマ(私はSteveと呼ぶでしょう)は、それを解決するための独自の問題とアルゴリズムを提供します。私はフレームワーク(ネットワーク、ユーザーインターフェイスなど)を提供するだけです。 Steveのプログラムにはいくつでも設定が必要な場合があります。自分の設定が(GUIコントロールパネルやXML設定ファイルなどから)自分の設定を取得するのと同じ方法で、自分のコードをユーザから取得できるようにしたい。スティーブは自分のコードを複製する必要はありませんし、Javaの型安全性やカプセル化モデルを破る必要もありません。

理想的には、スティーブは、これらの線に沿って何かを書くことができるようになります

public class SteveClass extends MyFrameworkClass { 

    @Configurable 
    private int foo; 

    @Configurable 
    private String bar; 

    private boolean baz; 

    // implementations of my abstract methods, etc. 

} 

Configurableは、注釈付きの変数が、私は、ユーザーから取得する必要があり、構成設定であることを示していること、私が提供する注釈です。ご覧のとおり、私はSteveが自分の内部使用のために他のインスタンス変数を宣言できるようにしたいと思います。

MyFrameworkClassには、getClass().getDeclaredFields()を繰り返し、Configurableアノテーションを持つフィールドを識別するメソッドを含めることで、これを実装しようとしていました。次に、これらのフィールドにユーザー入力を書き込みます。注釈とすべてで、これを正確に見る必要はありませんが、あなたはそのアイデアを得ることができます。

もちろん、この問題は、foobarがプライベートであり、MyFrameworkClassのコードは、それをそのまま反映することはできません。スティーブのコードは私と同じパッケージには入っていないので、パッケージ非公開であれば助けにならないでしょう。私は彼に公開させたり、他の誰かを許可するインターフェイスを追加する必要はありません私はフィールドにアクセスする。

SecurityManagerで手を加えるか、まったく違うことをして、私が欲しいことをする方法はありますか?

+0

マップを使用してパラメータを保存する方法と、変数名を格納するリストを使用する方法について教えてください。マップを使用して直接作業することができます(パラメータを繰り返して取得するか、パラメータ名を含むListを持つことができます)。 – Manish

+0

@ManishSharmaタイプの安全性。 – Taymon

+0

'protected'キーワードを使用して、サブクラスのアクセスを許可します。スーパークラスがサブクラスの保護されたフィールドにアクセスするためにリフレクションを使用しようとしたときに、JVMが何を考えるのか分かりません。 – Dunes

答えて

1

Class.getDeclaredFieldsを使用すると、クラスの宣言フィールド(非公開フィールドも含む)をすべて取得し、次にField.setAccessible(true)を使用してそのフィールドにアクセスできます。

Field foo = HasPrivate.class.getDeclaredField("foo"); 
foo.setAccessible(true); 
SteveClass steve = new SteveClass(); 
System.out.println(steve); // "0" -- I set up SteveClass.toString() to just print foo 
foo.setInt(hp, 1234); 
System.out.println(steve); // "1234" 

しかし、これを行うには、SecurityManagerに依存していることを意味します。これはデフォルトでは実行されますが、それはすべてのユーザーにとって機能しない可能性があります。これが厳しい要件である場合、他の便利ではありませんが、より堅牢なオプションがあります(コンストラクタがConfigurationオブジェクトを取得し、ユーザが値を取得できるようにするなど)。

+0

原則として、別のオブジェクトを介してデータを渡すことに異論はありませんが、タイプサフィーの方法?私はまだ同じ問題を抱えているようだ。 – Taymon

+1

あなたはタイプセーフであることに依存します。あなたは 'Configuration.getInt(" foo ")'、 'Configuration.getString(" bar ")'というメソッドを持つことができ、設定が正しくない場合に例外をスローすることができます。どのフィールドにどの型が必要なMap >を返す注釈付きの静的静的メソッドを提供することもできます。これにより、入力をより熱心にチェックすることができます(しかし、宣言と実際の 'フィールドごとに呼び出されるConfiguration.getXxx()メソッド)。 – yshavit

0
  1. 私はこれが委任と呼ばれていると思わ設定インタフェース

    public class SteveClass extends MyFrameworkClass { 
        private Configuration configuration ; 
    
        // implementations of my abstract methods, etc. 
    
    } 
    

を使用

interface Configuration 
{ 
    int foo () ; 

    String bar () ; 
} 
  • 設定インタフェースを作成します。

  • +0

    私は構成変数を指定しないので、これは私の問題を解決しません。 – Taymon

    2

    私があなたの立場にいたなら、私はこれを行うためにSpringフレームワークを使用する方法を見つけようとしています。これは、ユーザーがこれを書いてみましょうになります。あなたがしなければならないと思います

    @Component 
    public class SteveClass { 
        @Value("${steve.foo}") 
        private int foo; 
    
        @Value("${steve.bar}") 
        private String bar; 
    
        private boolean baz; 
    
        @Autowired(required = false) 
        private DaveClass dave; 
    } 
    

    すべてはそれ内で利用可能なこれらの性質を有するコンテキストを構築することです。それはかなり簡単です。 (春はセキュリティシーンの背後を突き抜けますが、正しい方法でこれを行います;あなたがする必要があるのは、Springが信頼され、残りのコードがほぼ同じレベルのアクセス権を必要としないようにすることだけですもちろん、スティーブにも彼のアプリを作るのに役立つたくさんのツールがありますが、それは別の質問の話です。

    +0

    もちろん、舞台裏では、春はyshavitが言及しているテクニックを使用しています。しかし、それは彼らを使用するのにはとても不便です。 –

    +0

    私はそれに精通していません。私はそれを調べます。 – Taymon

    +0

    @Taymon:私は、GUIの設定でどのように動作するかについてあまり知らないと言及する必要があります。私は最近、インタラクティブな表示がないサーバー側のソフトウェアを書く傾向があります... –