親から子クラスを返します。 オプショナル

これはどのような目的で必要になるでしょうか? たとえば、「 流体インターフェース 」を使用する場合。 確かに、メソッドの一部が親クラスに配置されている場合、それらが本格的な「流体インターフェース」を作成することは機能しません。これらのメソッドは子にキャストする必要があります。

それはその悲しみとだけのように思えますが、本当に望むなら、それはできます。 したがって、ルールを少し破って、その継承者の親クラスに「通知」しましょう。

したがって、初期状態( commit )があります。

1)必要なすべてのメソッドを知っているIChildParamインターフェイス
2)親クラスBaseClass
1) ChildClass下位ChildClass
 public interface IChildParam { int getBaseParam(); int getChildParam(); <T> T setBaseParam(int i); <T> T setChildParam(int i); } 
 public abstract class BaseClass implements IChildParam { private int baseParam; public int getBaseParam() { return baseParam; } public BaseClass setBaseParam(int i) { this.baseParam = i; return this; } } 
 public class ChildClass extends BaseClass { private int childParam; public int getChildParam() { return childParam; } public ChildClass setChildParam(int i) { this.childParam = i; return this; } } 


また、 setBaseParam setChildParamsetChildParamを呼び出すための3つの可能なオプションを記述する小さなテストクラスを作成しsetChildParam
 public class ClassTest { public static final int BASE_PARAM = 1; public static final int CHILD_PARAM = 2; @DataProvider(name = "data") public static Object[][] data() { final ChildClass item0 = (ChildClass) new ChildClass().setBaseParam(BASE_PARAM); item0.setChildParam(CHILD_PARAM); final ChildClass item1 = (ChildClass) new ChildClass().setChildParam(CHILD_PARAM).setBaseParam(BASE_PARAM); final ChildClass item2 = ((ChildClass) new ChildClass().setBaseParam(BASE_PARAM)).setChildParam(CHILD_PARAM); return new Object[][]{{item0}, {item1}, {item2}}; } @Test(dataProvider = "data") public void testChildClass(final IChildParam item) throws Exception { Assert.assertEquals(item.getBaseParam(), BASE_PARAM); Assert.assertEquals(item.getChildParam(), CHILD_PARAM); } } 


そして、ここにコードのキャッチがありますsetBaseParamメソッドを呼び出した直後にsetChildParamメソッドを呼び出す代わりに、最初に型変換を実行してからsetChildParamを呼び出す必要があります。 いずれにしても、 ChildClassへの明示的な型ChildClassが必要ChildClass

さて、この「誤解」を修正しましょう。

最初に、インターフェイスの宣言を変更しましょう-Genericレベルをメソッドレベルからインターフェイスレベルに削除します。
 public interface IChildParam<T> { int getBaseParam(); int getChildParam(); T setBaseParam(int i); T setChildParam(int i); } 


次に、 BaseClassクラスの宣言に変更を加え、「自分自身」の汎用タイプを追加します。
 public abstract class BaseClass<T extends BaseClass> implements IChildParam<T> { private int baseParam; public int getBaseParam() { return baseParam; } public T setBaseParam(int i) { this.baseParam = i; return (T) this; } } 


メインコードの変更の最後の手順は、子クラスの宣言を変更することです。
 public class ChildClass extends BaseClass<ChildClass> { private int childParam; public int getChildParam() { return childParam; } public ChildClass setChildParam(int i) { this.childParam = i; return this; } } 


さて、「流体インターフェース」をフルに使用してテスト内のコードを書き換えることを妨げるものは何もありません。
だった:
 final ChildClass item0 = (ChildClass) new ChildClass().setBaseParam(BASE_PARAM); item0.setChildParam(CHILD_PARAM); final ChildClass item1 = (ChildClass) new ChildClass().setChildParam(CHILD_PARAM).setBaseParam(BASE_PARAM); final ChildClass item2 = ((ChildClass) new ChildClass().setBaseParam(BASE_PARAM)).setChildParam(CHILD_PARAM); 
になりました:
 final ChildClass item0 = new ChildClass().setBaseParam(BASE_PARAM); item0.setChildParam(CHILD_PARAM); final ChildClass item1 = new ChildClass().setChildParam(CHILD_PARAM).setBaseParam(BASE_PARAM); final ChildClass item2 = new ChildClass().setBaseParam(BASE_PARAM).setChildParam(CHILD_PARAM); 


結果コミット

PS:もちろん、私たちは何も違反せず、親クラスは何も知らず、その相続人については無知のままでしたが...しかし、今ではメソッドから、相続人と同じ型を返すことができます。 。

UPD.0: コメントの が追加されました
UPD.1: コメントの を追加

Source: https://habr.com/ru/post/J234945/


All Articles