
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で質問しましょう!
似たような質問が見つかりました
- Java java 飾子を付けること(public static・・・) ・コンソールへの出力処理はmainメ 2 2022/06/16 19:34
- Java Java プログラム public class Main { public static void 3 2023/08/10 23:46
- Java java final 1 2022/06/10 22:49
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- 数学 【数学の図形の名称と面積の計算方法】正三角形と扇形があります。正三角形の2辺を伸ばす 9 2023/02/06 23:30
- Java javaの質問です 次の機能を有するメソッド4つを自クラスに作成し、実装したいです 【機能】 足し算 1 2022/06/15 17:49
- Java 直し方について教えて頂きたいです。 4 2022/08/13 02:11
- Ruby 【JAVA】数字をひし形に出力するプログラムについて 2 2022/07/11 23:32
- その他(プログラミング・Web制作) 3Dモデルにおける法線の計算について(Python,OpenGL) 1 2023/04/25 23:46
- Java JavaのSingletonパターンのprivateの持つ意味が分かりません。 5 2022/06/12 10:38
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ファイルパスが取得出来ない(P...
-
(vba)他のアプリケーションの右...
-
VB DLLプロジェクトについて
-
抽象クラスをJUNITでテストする...
-
メソッドの公開レベルとか設計とか
-
委譲って何ですか?
-
ASP.NETでの共通コードの書き方...
-
「継承されたメソッドの可視性...
-
「ラッパークラス」の存在意義...
-
Javaのインスタンス化の構文の...
-
デバッグ時に「Source not found」
-
javaでクッキー認証を必要とす...
-
C# 「データが失なわれる可能性...
-
抽象クラスのエラーが出ます
-
Commons-Discovery.jarとは?
-
C#からDLLを呼びたいのですが・...
-
クラスについての質問です!!
-
vb.net 自作プロパティの削除に...
-
【設計思想の質問】staticメソ...
-
プログラム超初心者です。
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C# 「データが失なわれる可能性...
-
「継承されたメソッドの可視性...
-
(vba)他のアプリケーションの右...
-
【C#】クラスのコンストラクタ...
-
VB DLLプロジェクトについて
-
メソッドの引数にクラス名を渡す
-
「ラッパークラス」の存在意義...
-
interface,extend,implementの...
-
c++でのヘッダーファイルの循環...
-
このエラーメッセージの意味を...
-
委譲って何ですか?
-
ゲッターを使わないで変数にア...
-
Javaのインスタンス化の構文の...
-
ファイルパスが取得出来ない(P...
-
ASP.NETでの共通コードの書き方...
-
Commons-Discovery.jarとは?
-
デバッグ時に「Source not found」
-
JTextFieldの入力制限
-
JavaのimplementsをC言語で例え...
-
オーバーライドとラッパーの違い
おすすめ情報