クラス設計から実装
クラスの設計〜実装までの簡単な流れを記載したいと思います。いよいよ基本レベル2のプログラミングの始まりです。
余談
よく世間巷では「オブジェクト指向言語」などという言葉が使われていますが、これは「オブジェクト指向で作りやすい」という意味で使用します。オブジェクト指向という言葉がいろんな意味で解釈されているので(同様に、関数型も。。。)使用しません。逆に使用されていたら無視してください。
基本レベル2
筆者の考えですが、プログラミングの学習を行うのには、3つの段階があると思っています。その段階は次のようになると考えます。
- 基本文法の理解をする段階
「基本レベル1」 - クラスとクラスの関係を作り、一つの仕組みを作るための知識を得る段階
「基本レベル2」 - 新しい仕組みをくみ上げる、新しいテクノロジーを追求する段階
「応用編」
そして、今回は基本レベル2の段階に学習を進めようというところです。
まずは、クラスの継承方法、抽象クラス、インターフェースの作り方を覚えましょう。
次に、ポリモーフィズムを理解しましょう。
まずは、クラスを作るときの基本的な考え方を理解しましょう。
よくないプログラムの例
public class Sample_Array { public static void main(String[] args) { // 1次元配列 String[] lv1Array = new String[] {"a", "b", "c"}; // 2次元配列 String[][] lv2Array = new String[][] {{"a", "b", "c"}, {"d", "e", "f"}}; // 3次元配列 String[][][] lv3Array = new String[][][] { {{"a", "b", "c"}, {"d", "e", "f"}} ,{{"g", "h", "i"}, {"j", "k", "l"}} ,{{"m", "n", "o"}, {"p", "q", "r"}} }; // 1次元配列を表示する System.out.println("*** 1次元配列を表示 ***"); for (String nakami : lv1Array) { printf("", nakami); } // 2次元配列 System.out.println("\n*** 2次元配列を表示 ***"); for (String[] nakamiLv2 : lv2Array) { for (String nakami : nakamiLv2) { printf("", nakami); } } // 3次元配列 System.out.println("\n*** 3次元配列を表示 ***"); for (String[][] nakamiLv3 :lv3Array) { for (String[] nakamiLv2 : nakamiLv3) { for (String nakami : nakamiLv2) { printf("", nakami); } } } } private static void printf(String label, String value) { System.out.print(label + "" + value); } }
ポイントとしては、以下の部分が良くないプログラムです。
- プログラムのほとんどを1つのメソッドに書いているので、変更を加えようとすると必ずこのファイルを修正しないといけません。
- 処理の内容が少ないので問題ありませんが、処理が分割されておらず「〜の処理はXXXにまとめる」というように処理が分割されていない。
結局は小さなプログラムではあまり効果がないのですが、何かのアプリケーションを作成しようとした時に威力を発揮します。
|
簡単なアプリを作る
コンソールアプリになりますが、簡単に作成して行こう思います。まずは設計です。
設計を行うことで、「プログラムをどのように組むか?」というところを考えます。はっきり言って答えがないので考え続けることになると思います。
しかし、これができれば、プログラミングはもっと面白くなり、世間にも貢献できるようになるかもしれません。
まずは、考えるための材料をゲットしましょう。※知識を取得しましょうという意味です。
クラス図について知識をゲットしましょう。
UMLで設計関連のページ
- UMLとは?
- 開発工程について
- UMLの体型(〜図がたくさんある)
- UMLの共通要素
- ユースケース図の書き方
- クラス図の書き方
詳細部分に関しては上記のリンク先を参照していただきたく思います。が簡単に「ATMのようなアプリケーション」を作成してみようと思います。
全体の流れ(ユースケース)
「全体の流れ」と記載しましたが、「人が使うときの流れ=ユースケース」になります。
実際のATMとはかけ離れてしまいますが。。。
<ユースケース>
【前提】
- コンソール画面のATMとします。
- ユーザー認証は行いません。
- 単純に金額を入金、引き出しができるものを作ります。
【仕様】
- アプリを起動してコンソールから「引き出す」「入金」を選択する
- それぞれの処理に対して「預金額」から足し算、引き算を行いその結果を表示する
仕様としては単純なものです。これをサンプルとして作成することを考えます。
必要な機能を考える
はっきり言ってこの部分には「正解」というものがありません。
ある意味「なんでも良い」のかもしれませんが、なるべく効率の良いものを作りたいと思うのが人情です。
そのために必要なことは以下のようになります。
無駄な処理を行わない
ということです。そのためにクラスを作成し役割分担を行います。
上のケースで行くと、以下の要件が出てきます。
- 「引き出し」と「入金」の2つをハンドルする処理が必要
- 「引き出し時の処理」と「入金時の処理」が必要
- 最終的にコンソールへ出力する処理が必要
大雑把に3つの要件が出てきます。
要件を満たす部品を考える
【前提】
コンソールアプリなのでメインメソッドを動かす中で全ての作業(入金、引き出しなど)を表現します。
<部品候補>
- メインメソッドを持ち、入力の受付も行うクラス
- 入金、引き出しを行う計算処理クラス
2つの部品を作る事で、役割を分担し、要件を満たすことができそうです。しかし、これでよいのかどうか?自分で考えてみましょう。
筆者が作成したのは、こんな感じです。ソースはGithubにあります。
結局、5個くらいのクラスを作成した形になりました(笑)。
<動画その1>
<動画その2>
でわでわ。。。