質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

9072閲覧

共通部分と独自処理が含まれる場合の継承[java]

hanayamaKaoru

総合スコア36

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2016/08/09 13:56

###前提・実現したいこと
前回、うまく質問できなったので再度質問します。
インターフェースをimplementsすると実装は共通部分が多いのでコピペを行うことになり、保守性が下がる。

そのため
実装が
①共通
②独自
③共通
と独自の処理が共通処理で囲まれている場合
以下のコードのように
①の共通部分を行うfirstRun()
③の共通部分を行うLastRun()
を定義したクラス(ControlDamage)を継承し独自処理をfirstRun()とLastRun()の間に記述することにしました
この解決策はナンセンスでしょうか?

*DecreaseDamageByBerryとIncreaseDamageByBerryでは独自処理を行うことでパラメータが変化しLastRun()の結果が変わる。

###該当のソースコード

java

1public abstract class Ability { 2 protected ArrayList<Object> params= new ArrayList<Object>(); 3 4 protected Ability(ArrayList<Object> params) { 5 this.params = params; 6 } 7 8 public abstract void run(); 9 10}

java

1public abstract class ControlDamage extends Ability { 2 protected Magnification magnification; 3 protected int i =0; 4 ControlDamage(ArrayList<Object> params) { 5 super(params); 6 // TODO 自動生成されたコンストラクター・スタブ 7 } 8 9 protected void firstRun(){ 10 /*共通部分前半処理*/ 11 12 } 13 14 protected void lastRun(){ 15 /*共通部分後半処理*/ 16 } 17 18} 19

java

1public class DecreaseDamageByBerry extends ControlDamage { 2 3 DecreaseDamageByBerry(ArrayList<Object> params) { 4 super(params); 5 6 } 7 8 @Override 9 public void run() { 10 // TODO 自動生成されたメソッド・スタブ 11 super.firstRun();/*共通部分前半*/ 12 13 /*共通ではない部分を処理*/ 14 15 super.lastRun(); //共通部分後半 16 17 18 } 19 20 21}

java

1public class IncreaseDamageByBerry extends ControlDamage { 2 3 DecreaseDamageByBerry(ArrayList<Object> params) { 4 super(params); 5 6 } 7 8 @Override 9 public void run() { 10 // TODO 自動生成されたメソッド・スタブ 11 super.firstRun();/*共通部分前半*/ 12 13 /*共通ではない部分を処理*/ 14 15 super.lastRun(); //共通部分後半 16 17 18 } 19 20 21}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

この解決策はナンセンス

ということはありません。

この実装方法は "テンプレートメソッド・パターン" と呼ばれるデザインパターンの1つです。
https://ja.wikipedia.org/wiki/Template_Method_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3

ただし、ご提示のソースコードは以下の部分が冗長に感じられます。
0. AbilityクラスとControlDamageクラスは1つにまとめることが可能。
0. run メソッドを abstract メソッドとして定義する必要はない。

私なら、以下のように定義・実装します。

java

1import java.util.List; 2 3public abstract class Ability { 4 protected List<Object> params; 5 6 protected Magnification magnification; 7 protected int i = 0; 8 9 protected Ability(List<Object> params) { 10 this.params = params; 11 } 12 13 public void run() { 14 firstRun();/*共通部分前半*/ 15 16 /*共通ではない部分を処理*/ 17 originalRun(); 18 19 lastRun(); //共通部分後半 20 } 21 22 private void firstRun(){ 23 /*共通部分前半処理*/ 24 } 25 26 private void lastRun(){ 27 /*共通部分後半処理*/ 28 } 29 30 protected abstract void originalRun(); 31}

java

1import java.util.List; 2 3public class DecreaseDamageByBerry extends Ability { 4 5 DecreaseDamageByBerry(List<Object> params) { 6 super(params); 7 } 8 9 @Override 10 protected void originalRun() { 11 /*共通ではない部分を処理*/ 12 } 13}

java

1import java.util.List; 2 3public class IncreaseDamageByBerry extends Ability { 4 5 IncreaseDamageByBerry(List<Object> params) { 6 super(params); 7 } 8 9 @Override 10 protected void originalRun() { 11 /*共通ではない部分を処理*/ 12 } 13}

run(), firstRun(), lastRun() メソッドをAbilityクラスで実装し、「共通でない部分を処理」する originalRun() メソッドだけを abstract として定義すれば、Abilityクラスのサブクラスはこのメソッドだけを実装すればよいことになります。


ちなみに、Abilityクラスの全てのサブクラスに

run メソッドを呼び出すと ①firstRun() ②originalRun() ③lastRun() を順番に実行する

ことを強制したいのであれば、run メソッドに final 修飾子を追加してやればよいです。

投稿2016/08/09 15:22

KiyoshiMotoki

総合スコア4791

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Java8 では default メソッド が利用可能になっています。

java

1public interface A { 2 default void b(String s) { System.out.println(s); } 3}

とかけます。

以前は

java

1public interface A { 2 public void b(String s); 3} 4 5public abstract class B implements A { 6 public void b(String s) { System.out.println(s); } 7} 8

と abstract クラスを挟むことで対応されていました。

詳しくは java Collection Framework のクラス群が後者の方法をつかっているので見てみるといいです。

投稿2016/08/09 14:02

asahina_dev

総合スコア610

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問