これが私が実際に直面している私の問題です。私にはクラスがあります。たとえば、Foo
としましょう。このクラスは、getBar
インスタンスを返すBar
というメソッドを定義します。クラスBar
はFoo
内で定義され、_public static final
_として宣言されます。私がやりたいことは、MyFoo
を拡張するFoo
クラスを定義することですが、Bar
をMyBar
で拡張して、独自の機能(メソッド、プロパティなど)を追加することもできます。また、getBar
がMyBar
を返すようにします。
問題は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のプラグインを開発していて、検索した後、やりたい基本機能を提供するプラグインがあることに気付きました。Foo
とBar
です。 Foo
とBar
をカスタマイズして、自分のニーズに合うようにします。 Fooはプラグインのメインクラスで、Builderと呼ばれるクラスを拡張します。 Fooは、ビルドを実行するためのすべての操作を含むperform
というメソッドを定義します。 Bar
には構成目的の操作が含まれており、Fooはそれらの情報を取得するためにBarを必要とします。
したがって、私がやりたいのは、MyFoo
でFooを拡張し、MyBar
でいくつかの構成を追加することです。そしてご覧のとおり、MyFoo
はgetBar();
を呼び出してこれらの構成を取得する必要があります
2つ目は、MyFoo
およびMyBar
のインスタンス化を制御できないことです。
私を妨げているのは、Barを拡張できないことです。どうすればそれを達成できますか?
基本的にはできません。拡張しないようにBar
を設計した開発者のようです-したがって、拡張できません。別のデザインを探す必要があります-継承をあまり使用しないものかもしれません...もちろん、既存のコードを変更できない場合を想定しています。
(ここでの実際の目標、つまりシステム全体の設計についての詳細を知らずに、より具体的なアドバイスをすることは困難です。)
final
と宣言されているクラスを拡張することはできません。ただし、Wrapper
という中間クラスを作成できます。このラッパーには、基本的に元のクラスのインスタンスが含まれ、目的に応じてオブジェクトの状態を変更するための代替メソッドが提供されます。
もちろん、これはfinal
クラスのプライベートフィールドと保護フィールドへのアクセスを許可しませんが、そのゲッターメソッドとセッターメソッドを、Wrapper
で宣言した新しいメソッドとフィールドと組み合わせて使用できます。希望する結果、または比較的近いものを取得するクラス。
別の解決策は、正当な理由がない場合にfinal
クラスを宣言しないことです。
final
クラスを拡張することはできません。これがfinal
キーワードの目的です。
ただし、(少なくとも)2つの回避策があります。
Finalクラスを拡張することはできません。つまり、クラスをfinalと宣言するポイントです。最終クラスが継承するインターフェイスと、ラップされた最終クラスへの呼び出しを委譲するラッパークラスの両方を定義できます。問題は、そもそもなぜクラスを最終的なものにするのかということです。
おそらくあなたが望むのはプロキシです。実装は簡単です。これはすばらしい記事です: http://Java.dzone.com/articles/power-proxies-Java
一部のインターフェースを実装している場合、 Decorator Design pattern で問題を解決できます。
たとえば、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);
}