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

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



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



したがって、初期状態( 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



setChildParam



setChildParam



を呼び出すための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: コメントの を追加



All Articles