24

これが私が今直面している私の問題です。たとえば、クラスがあり、このクラスはインスタンスを返すというFooメソッドを定義します。クラスは内部で定義され、宣言されています。私がやりたいのは、拡張するクラスを定義することですが、独自の機能(メソッド、プロパティなど)を追加して拡張することもできます。私も戻りたいです。getBarBarBarFoopublic static finalMyFooFooBarMyBargetBarMyBar

問題はBar最終的なものです。これが私がやりたいことのイラストです:

public class Foo {

  Bar bar = new Bar();

  public Bar getBar(){
      return bar;
  } 

   ....

   public static final class Bar {

    } 
}

私がしたいのは:

public class MyFoo extends Foo {


   public MyBar getBar(){ // here I want to return an instance of MyBar

   }

  public static final class MyBar extends Bar { // That's impossible since Bar is final

  } 
}

どうすればそれを達成できますか?

[編集]質問に詳細を追加しています。私は実際にJenkinsのプラグインを開発していますが、検索したところ、やりたい基本機能を提供するプラグインがあることに気付きましFooBarFoo私はカスタムしたいBarので、それは私のニーズに合うことができます。Fooはプラグインのメインクラスであり、Builderと呼ばれるクラスを拡張します。performFooは、ビルドを実行するためのすべての操作を含む というメソッドを定義します。Bar構成目的の操作が含まれており、Fooはそれらの情報を取得するためにBarを必要とします。

だから私がやりたいのは、Fooを拡張しMyFoo、でいくつかの構成を追加することMyBarです。ご覧MyFooのとおり、これらの構成を呼び出す必要がありますgetBar();

MyFoo2つ目は、とのインスタンス化を制御できないことです。MyBar

私を阻んでいるのは、バーを拡張できないことです。どうすればそれを達成できますか?

4

7 に答える 7

37

基本的にはできません。拡張されないように設計した開発者のように見えるBarので、拡張することはできません。別の設計を探す必要があります。おそらく、継承をあまり使用しない設計です...もちろん、既存のコードを変更できないと仮定します。

(ここでの本当の目標、つまりシステム全体の設計について詳しく知らずに、より具体的なアドバイスを提供することは困難です。)

于 2012-11-08T17:42:11.220 に答える
13

宣言されているクラスを拡張することはできませんfinal。ただし、と呼ばれる中間クラスを作成できますWrapper。このラッパーには基本的に元のクラスのインスタンスが含まれ、実行したい内容に応じてオブジェクトの状態を変更するための代替メソッドを提供します。

もちろん、これではfinalクラスのプライベートフィールドと保護フィールドにアクセスできませんが、そのgetterメソッドとsetterメソッドを、Wrapperクラスで宣言した新しいメソッドとフィールドと組み合わせて使用​​して、必要な結果を得ることができます。選ぶ。

final別の解決策は、正当な理由がない場合にクラスを宣言しないことです。

于 2012-11-08T18:43:37.213 に答える
9

finalクラスを拡張することはできません-それがfinalキーワードの目的です。

ただし、(少なくとも)2つの回避策があります。

  1. クラスはオープンソースのJenkinsプロジェクトに含まれているため、プロジェクトをダウンロードし、クラスに必要な変更を加えて、jarを再構築するだけです。
  2. ややハックですが、Javassistのようなライブラリを使用して、メモリ内のクラスの実装を置き換えることができます
于 2012-11-08T22:32:25.827 に答える
4

最終クラスを拡張することはできません。つまり、クラスを最終として宣言する必要があります。最終クラスが継承するインターフェイスと、ラップされた最終クラスへの呼び出しを委任するラッパークラスの両方を定義できます。問題は、そもそもなぜクラスを最終的なものにするのかということです。

于 2012-11-08T17:42:49.453 に答える
3

おそらくあなたが欲しいのはプロキシです。実装は簡単です。これは素晴らしい記事です:http://blog.frankel.ch/the-power-of-proxies-in-java

于 2014-09-18T21:10:37.500 に答える
0

たとえば、TreeSetはInterface Comparableの子ではないため、TreeSetコレクションにStringBufferを追加することはできません。

public class Main(){
public static void main(String[] args){
   TreeSet treeSetSB = new TreeSet();
   treeSetSB.add(new StringBuffer("A"));  //error, Comparable is not implemented
}

ただし、ラッパーを使用してComparableを実装できます。

class myWrap implements Comparable{
    TreeSet treeset;
    public myWrap() {
        this.treeset=new TreeSet<>();

    }
    public TreeSet getTreeset() {
        return treeset;
    }
    public void setTreeset(TreeSet treeset) {
        this.treeset = treeset;
    }
}


public class Main(){
public static void main(String[] args){

   myWrap myWrap =new myWrap();
   TreeSet myTrs  =myWrap.getTreeset();
   myTrs.add("b");   // no error anymore
   myTrs.add("a");
   myTrs.add("A");
   System.out.println(myTrs);
}
于 2016-10-09T08:13:20.153 に答える
0

いくつかのインターフェイスを実装している場合、デコレータデザインパターンで問題を解決できます。

于 2018-03-08T13:04:00.717 に答える