EclipseでJavaを勉強始めました。
抽象クラスからオーバーライドするところで質問致します。
抽象クラスとして、「面積を計算する」というメソッドをもつDiagramクラスを定義しました。それを継承して、「四角形の面積を計算する」というメソッドをもつSquareクラスと、「三角形の面積を計算する」というメソッドをもつTriangleクラスを定義しました。
Squareクラス、Triangleクラスからインスタンスを生成して、四角形、三角形の面積をコンソールに表示させるという簡単なプログラムです。
このとき、main関数と3つのクラスの関係についてお尋ねします。
(1)iagram.java、Square.java、Triangle.javaそれぞれにクラス定義とmain関数を持たせるパターン
public abstract class Diagram {
// 面積計算定義(抽象メソッド)
public static void main(String[] args) {
}
}
public class Square extends Diagram{
//四角形の面積の計算定義
public static void main(String[] args) {
//四角形の面積の計算と表示
}
public class Triangle extends Diagram{
//三角形の面積の計算定義
public static void main(String[] args) {
//三角形の面積の計算と表示
}
(2)sample.javaというファイルにまとめ、その中にこの3つのクラス定義とmain関数を一つ持たせるパターン
public class sample {
public static void main(String[] args) {
//四角形の面積の計算と表示
//三角形の面積の計算と表示
}
}
abstract class Diagram {
// 面積計算(抽象メソッド)定義
}
class Square extends Diagram{
//四角形の面積の計算定義
}
class Trapezoid extends Diagram{
//三角形の面積の計算定義
}
この二通りを考えて、どちらも実行できたのですが、どちらの方がJavaらしいプログラムと思われますでしょうか?
No.6ベストアンサー
- 回答日時:
そもそも、オブジェクト指向設計の目的は、
<1>作成したクラスに再利用性がある(を持たせる)
<2>将来の仕様変更に対して最小限の修正で済む
事を第一の目的にしています。
(1)は明らかに問題があります。
例えば(1)も場合に、値をファイル出力するとなったらどうでしょうか?
面積を計算している部分の含まれたソースコードを触らなければ
いけなくなっています。
面積の計算と出力は全く関係ありませんので、ソース上くっついていては
殆ど再利用性が無いと言う事になってしまっています。
(また、mainメソッドをオーバーライドするのも非常に不自然です)
(2)では、1つのファイルにまとめてしまってはいけません。
なぜなら、Squareクラスに関するJavaDocが独立して存在しませんので、
sampleクラスを見るまでその存在に気付けません。
ということは、再利用性が閉ざされているということです。
なお、本例のような場合には、Diagramはインターフェースの方が良いです。
ちょうど、java.awt.Shapeインターフェースに対して、java.awt.Polygonや
Line2D具象クラスが存在するのと同じ関係にするということです。
簡単に具体例を示してみると、
-- Diagram.java ---
interface Diagram {
double solveArea(); // 面積を計算する
double solvePeriphery(); // 外周を計算する
}
-- Square.java ---
public Square implements Diagram {
private ... // 四角形のパラメータ
public Square( ... ) {
...
}
public double solveArea() {
// 四角形の面積の具体的な計算
return area;
}
public double solvePeriphery() {
// 四角形の外周の具体的な計算
return length;
}
}
-- Trapezoid.java ---
public Trapezoid implements Diagram {
private ... // 三角形のパラメータ
public Trapezoid( ... ) {
...
}
public double solveArea() {
// 三角形の面積の具体的な計算
return area;
}
public double solvePeriphery() {
// 三角形の外周の具体的な計算
return length;
}
}
そして、これを実行するメインメソッドを持つクラスを作ります。
public class Sample {
public static void main(String[] args) {
Diagram diagram = new Square( ... );
double ans = diagram.solveArea();
System.out.println( ans );
}
}
ここでは、四角形の面積を求めましたが、これを三角形の面積を
求めるように変更したいならば、mainメソッド内の1行目の右辺を
new Trapezoid( ... ); に書き換えれば済むわけです。
ここで、左辺をDiagramインターフェースで受けているのも重要で、
図形に関する処理が抽象化されるので汎用性が増しています。
同様に、面積から外周を求めるように変更したいならば、2行目だけを
solvePeriphery() 書き換えれば済みます。
この回答への補足
ご丁寧に有難う御座いました。改めて検討してみました。
ご指摘のとおり、
「面積計算」をインターフェースとして扱い、パッケージの中に
(1)Diagram.javaにDiagramインターフェース
(2)Square.javaにSquareクラス
(3)Trapezoid.javaにTrapezoid クラス
そして、
(4)Sample.javaにSampleクラス、ここにmainメソッドを書く
という方法、とてもよく理解できました!。
一方「面積計算」を抽象クラス(メソッドのみ持つ)として扱い、パッケージの中に
(1)はDiagram.javaにDiagram 抽象クラス
(2)Square.javaにSquareクラス(Diagram 抽象クラスを継承)
(3)Trapezoid.javaにTrapezoid クラス(Diagram 抽象クラスを継承)
そして、
(4)Sample.javaにSampleクラス、ここにmainメソッドを書く
という方法でも試してみましたが、
やはり、“「面積計算」をインターフェース”として扱うほうが、Javaらしいプログラムという理解でよろしいでしょうか?
No.7
- 回答日時:
>一方「面積計算」を抽象クラス(メソッドのみ持つ)として扱い、パッケージの中に
>・・・
>やはり、“「面積計算」をインターフェース”として扱うほうが、
>Javaらしいプログラムという理解でよろしいでしょうか?
すばらしい探究心ですね!
誰をも説得できる最強の理由は、『Effective Java』に
(項目16)抽象クラスよりインターフェースを選ぶ
と、書いてあるからです。
きっと、今後も将来的にプログラミングを続けていかれるでしょうから、
ぜひ、当該書籍を入手されることをお勧めします。
『Effrctive Java プログラミング言語ガイド』
http://www.amazon.co.jp/Effective-Java-%E3%83%97 …
実用上は、Squareクラスは、Shapeインターフェースも実装する必要があるでしょう。
public class Square implements Diagram, Shape {
...
}
要するに、ひとつの理由はJavaはクラスの多重継承が認められていないので、
インターフェースを持たない抽象クラスを書いてしまうと実用上問題が
出てくるということです。
(よく見かけるこの様な表現ですが、正確には、Javaは言語仕様として、
インタフェースを使った実装を推奨するために、クラスの多重継承を
禁止しているという方が正しいでしょう)
蛇足ですが、
データ構造,デザインパターン,UML
等の言葉をキーワードに書籍を入手されれば、より専門的な分野の
知識が身に付くかと思います。
Effective Javaの内容も決して平易ではないので、その内容を理解するために
別の書籍を購入するというのもとても良い方法だと思います。
この回答への補足
>ひとつの理由はJavaはクラスの多重継承が認められていないので、
VBだけかと思いましたが、Javaもそうだったんですね。
>インターフェースを持たない抽象クラスを書いてしまうと実用上問題が出てくるということです。
納得のいく説明ありがとうございます。
No.5
- 回答日時:
(2)の方がシンプルでいいですよね。
1ファイルに1publicクラスでなくていけない理由
http://q.hatena.ne.jp/1122966784
だるまのエクセルVBA トップ > オブジェクト指向についていろいろ > オブジェクト指向とモジュールの凝集度、モジュールの結合度
http://members3.jcom.home.ne.jp/daruma_kyo/about …
ちなみに、リンク張っといておいて何ですが、下の方はざ~っと眺めておくだけでいいです。とにかく、以下の2点を覚えておいてください。
良いクラス→
・結合度が弱い
・凝縮度が高い
No.4
- 回答日時:
勉強のためにやるなら(1)でも良いと思うけど、
私が、実際に作る場合は(2)で作ります。
表示までclassに持たせるのは、ちょっとどうかと思いますね。
No.1
- 回答日時:
どちらかを選べといわれれば(2)かな?
と思いますが、JAVAの基本は1クラス1ファイルなので、私なら全部クラス毎にファイルをわけるかなあ・・・と思います。
特に抽象クラスやインタフェースは、定義のみで実装は外部に任せるというイメージなので、少なくとも抽象クラスやインタフェースは別ファイルにすべきだと思われます。
まぁ、この程度のソースなら1つのファイルでも良いのでしょうが。
ありがとうございます。VBはかじったのですが、JAVAはよくわからなくて。
>全部クラス毎にファイルをわけるかなあ・
をもう少し教えていただければ幸いです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~11/12】 急に朝起こしてきた母親に言われた一言とは?
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・好きな「お肉」は?
- ・あなたは何にトキメキますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・チョコミントアイス
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・あなたの習慣について教えてください!!
- ・ハマっている「お菓子」を教えて!
- ・高校三年生の合唱祭で何を歌いましたか?
- ・【大喜利】【投稿~11/1】 存在しそうで存在しないモノマネ芸人の名前を教えてください
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・家の中でのこだわりスペースはどこですか?
- ・つい集めてしまうものはなんですか?
- ・自分のセンスや笑いの好みに影響を受けた作品を教えて
- ・【お題】引っかけ問題(締め切り10月27日(日)23時)
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・ちょっと先の未来クイズ第4問
- ・【大喜利】【投稿~10/21(月)】買ったばかりの自転車を分解してひと言
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
JTextFieldの入力制限
-
JAVAでCPUなどのシリアル番...
-
抽象クラスをJUNITでテストする...
-
C# 「データが失なわれる可能性...
-
ASP.NETでの共通コードの書き方...
-
委譲って何ですか?
-
インターフェースとトレイトっ...
-
「IOException は対応する try ...
-
「継承されたメソッドの可視性...
-
compareToにおける「自然順序付...
-
「タイプ初期化子が例外をスロ...
-
エクセルVBAで、条件に一致する...
-
変数名の付け方
-
private static という変数の修飾
-
インスタンス参照でアクセスで...
-
コマンドプロンプト実行後に画...
-
C#でフォームのオブジェクト名...
-
複数の変数を宣言する時、同時...
-
どこからも呼ばれていない無意...
-
パワーポイントのVBAでテキスト...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
「ラッパークラス」の存在意義...
-
C# 「データが失なわれる可能性...
-
interface,extend,implementの...
-
(vba)他のアプリケーションの右...
-
VB DLLプロジェクトについて
-
委譲って何ですか?
-
JavaでのAPIの覚え方ってみさな...
-
setTextについて
-
c++でのヘッダーファイルの循環...
-
【C#】クラスのコンストラクタ...
-
ASP.NETでの共通コードの書き方...
-
C#からDLLを呼びたいのですが・...
-
「継承されたメソッドの可視性...
-
抽象クラスをJUNITでテストする...
-
Commons-Discovery.jarとは?
-
JTextFieldの入力制限
-
「IOException は対応する try ...
-
Javaのインスタンス化の構文の...
-
オーバーライドとラッパーの違い
-
メソッドの引数にクラス名を渡す
おすすめ情報