<目次>
- オブジェクト指向の考え方と、Java言語における基本的なクラスの実装方法・利用方法を理解する。
- ドキュメンテーションツールJavadocに対応したコメントの書き方を理解する。
- TicTacToe.java // TicTacToeクラスを定義したファイル。
- ポイント
- 盤面情報を保存するフィールド変数 board と、手番管理用の変数 turn は private に指定 している。
- board, turn を直接編集するメソッドは提供していない。実装を隠蔽している(実装を気にせず利用できるように、機能をメソッドとして提供している)。
- ポイント
- Main.java // ゲームをプレイするmain()メソッドを含むクラス。
- プログラム等のダウンロード、コンパイル、実行手順
- ファイルの準備
- IntelliJで適当なGradleプロジェクトを用意。
- プロジェクト内の src/main/java の中にパッケージを追加。今回は「jp.ac.uryukyu.ie.tnal」。
- 上記パッケージ内に、TicTacToe.java をコピペ保存する。
- src/main/java 直下に Main.Java をコピペ保存する。パッケージ内ではない点に注意。
- ただの実行
- Main.java を実行。
- ドキュメント生成の手順
- ドキュメントの保存場所を用意。
- プロジェクト内に docs フォルダを作成。
- IntelliJのメニュー「Tools」から、「Generate JavaDoc」を選択。
- 中段にある「Output dicrectory:」の右側で、先程用意したプロジェクト内のdocsを選択。
- 「OK」をクリック。
- ドキュメントの保存場所を用意。
- ドキュメントの参照手順
- 一度生成したドキュメントは全て docs フォルダに保存されている。このフォルダ内の
index.html
をブラウザで開けばいつでも閲覧できる。例えばプロジェクトが~/IdeaProjects/week4/
に保存されているならば、そこに移動して open コマンドで開けば参照できる。 - 誰かに提供したいなら、HTMLファイル単体ではなくこのフォルダ全体を渡そう。CSS等も使われているため。
- 一度生成したドキュメントは全て docs フォルダに保存されている。このフォルダ内の
- ファイルの準備
- 上記では IntelliJ 上でドキュメント生成したが、ターミナル上からも生成できる。
- ドキュメント生成方法
javadoc -private -d apidoc *.java
- オプション説明
- -private: private指定されてるメンバもドキュメントに含める。
- -d <directory_name>: -d で指定したディレクトリにドキュメントを生成する。
- 上記の例では apidoc というディレクトリに生成している。
- *.java: ドキュメント生成時に参照するソースコード。
- ドキュメントの参照方法
open apidoc/index.html
- ドキュメント生成方法
- ドキュメントの書き方
- ドキュメント例: TicTacToe.java
- クラスについて説明を書くなら「クラスの直前」に、指定書式で書く。
- メソッドや変数についても各場所は同様に「直前」に書く。
- クラス・フィールド変数・メソッドの前に下記書式でコメントを書く。
- 必ず
/**
という行から書き始めること。javadoc はこの行を参考にドキュメントを生成する。(//
で書いたコメントは無視される)
- 必ず
- よく使うオプション
- @param パラメータ
- @return 戻り値
- @deprecated 非推奨(「近い将来削除等の理由で使えなくなる」ということを明示するためのオプション)
- その他: Javadoc Tags
- ドキュメント例: TicTacToe.java
/**
* 1行概要。
* 詳細。
* @param パラメータ名 説明
*/
- Q1: なぜ、オブジェクト指向なのか
- A:
- あらゆるプログラムは「逐次処理・分岐・ループ」を関数化して積み重ねて作り上げることができる。
- ただし不便。もっと便利な記述したいよね?
- 一例が「オブジェクト指向」もしくは「オブジェクト指向プログラミング」。
- A:
- Q2: オブジェクト指向って何?
- A1: wikipediaによると次の通り。
- オブジェクト指向プログラミング(オブジェクトしこうプログラミング、英: object-oriented programming, OOP)とは、相互にメッセージ (message) を送りあうオブジェクト (object) の集まりとしてプログラムを構成する技法である。この技法をサポートするプログラミング言語はオブジェクト指向プログラミング言語 (object-oriented programming language, OOPL) と呼ばれる。オブジェクト指向プログラミングには必ずしもオブジェクト指向プログラミング言語を用いる必要は無いが、オブジェクト指向プログラミング言語の備えるクラスとその継承などの仕組みを利用するほうが格段に開発効率は向上する。
- A2: by 教科書
- 考え方、問題の捉え方を変える必要がある。
- まず、開発しようとするシステムから「対象」を抽出して分析し、クラスを作成する。
- 具体例「13.2 クラスの作り方」参照。
- 次に、クラスからオブジェクトを作ってシステムを構成する。
- 具体例「13.3 オブジェクトの作り方」、「13.4 オブジェクトの使い方」参照。
- A1: wikipediaによると次の通り。
- Q3: どう考えればよいの?
- A3: by 教科書, pp.289-
- 「オブジェクト(Object) = モノや対象」。
- (1)対象を抽出して、(2)その対象がどのようなデータを持っているか、(3)それらのデータをどう処理するメソッドを持っているのか、の3点をデザインする。このような考え方が「オブジェクト指向」。
- 「100%正しい設計」というものはない。まずは思いつく限りでの設計を。使いにくかったらその原因を取り除く方法について検討したり、よりよい設計を目にしたら参考にしていくようにしよう。
- A3: by 教科書, pp.289-
- トランプカードを例にクラス設計(pp.293-)
- 「スペードやハート」といった種類(データ)を持つが、どう表現したら良いだろうか?
- 「1〜13」といった数値(データ)を持つが、どう表現したら良いだろうか?
- ジョーカーはどう表現したら良いだろうか?
- オブジェクトの初期化の既定値(p.301)
- 用語サマリ
- オブジェクト: クラスに基づいて具体的なデータとメソッドを持つ実体。実体がない(オブジェクトがない)と、利用することができないので、利用する際にはまず実体をもたせる必要がある。
- 「diceオブジェクト」
- インスタンス: オブジェクトとほぼ同等。特にオブジェクトを初期化して用意することを「インスタンスを用意/作成/生成する」という。
- オブジェクトとインスタンスの違い
- 「オブジェクト」は、モノとしてのより一般的な意味合いを持つ。
- 「インスタンス」は、クラスから設計したもの。
- 「diceインスタンス」
- オブジェクトとインスタンスの違い
- クラス: モノ・対象に関する設計図。下記フィールド変数とメソッドで記述される。(設計図なので、直接クラスを変数のように扱うことはできない。勝手に設計図が書き変わると、あとで困るよね?)
- メンバ: 13.4節。クラスが持つ構成要素。ここではフィールド変数とメソッドの両方を指している。
- データ(フィールド変数): クラスが持つデータ。インスタンス生成時に設定することが多い。メソッドの外で宣言すること。
- メソッド: クラスが持つ機能。フィールド変数は引数として指定しなくても利用できる。フィールド変数以外は引数として渡そう。
- インスタンスメソッド: メソッドの一種。staticを付けない点に注意。詳細は後日。(教科書16章、18章)
- ローカル変数: そのメソッド内でしか利用できない変数。メソッドの処理終了時にメモリ上から廃棄される。メソッド外から参照することはできない。(returnしたものだけが他メソッドから利用できる)
- メンバ外の要素
- コンストラクタ: 14.1節。オブジェクト作成時に初期化する仕組み。作成されたオブジェクトはコンストラクタを持たない。持たないので、オブジェクト生成後に利用することもできない。
- メンバ: 13.4節。クラスが持つ構成要素。ここではフィールド変数とメソッドの両方を指している。
- オブジェクト: クラスに基づいて具体的なデータとメソッドを持つ実体。実体がない(オブジェクトがない)と、利用することができないので、利用する際にはまず実体をもたせる必要がある。
- コード例1
- IntelliJでの作業を推奨。適当なプロジェクトを作成し、そこに2つのクラスファイルを用意しよう。
- Math.random
//クラス例: Dice.java
public class Dice {
int val; //フィールド
//インスタンスメソッド
public void play(){
val = (int)(Math.random()*6) + 1;
}
}
//mainメソッドを別のファイルで用意: Exec.java
public class Exec {
public static void main(String[] args){
Dice dice = new Dice(); //オブジェクト生成(13.3節)
System.out.println(dice.val); //diceオブジェクトの利用(13.4節)
}
}
- クラス(設計図)を基に、インスタンス(オブジェクト)を作るためには
new
演算子を使う。new クラス名()
- ここでは「クラス名=コンストラクタ」。
- 複数のコンストラクタを設定している場合には、引数によって適切なコンストラクタが選ばれる。(詳細は14章にて)
- メンバ(構成要素)を参照するには
.
(ドット演算子, メンバ参照演算子) を使う。- フィールド変数を参照・設定する:
インスタンス名.フィールド変数名
- クラスメソッドを呼び出す・実行する:
インスタンス名.メソッド名()
- フィールド変数を参照・設定する:
- コンストラクタ=オブジェクト作成時に初期値を設定する仕組み。戻り値は設定できない。コンストラクタの役割は、生成したインスタンスを返すこと。
- this の利用
- オブジェクト自身のフィールド変数を利用する際に使う。
- 例:
this.フィールド変数名
- コード例2
- コンストラクタ、オーバーロードの例。
//クラス例: Dice.java
public class Dice {
int val;
String color;
//コンストラクタ
public Dice(int val){
this.val = val;
}
//コンストラクタのオーバーロード(14.2節)
public Dice(){
play();
}
public void play(){
val = (int)(Math.random()*6) + 1;
}
}
- コンストラクタは目的に応じて複数用意することができる。
- オーバーロード=同一名称で、異なる機能を用意すること。
- 使い分けるために引数構成(型、数、並び順)が異なっている必要がある。
- コンストラクタのオーバーロード=同一名称の、複数コンストラクタを用意すること。
- メソッドのオーバーロード=同一名称の、複数メソッドを用意すること。
- オーバーロード=同一名称で、異なる機能を用意すること。
- デフォルト・コンストラクタ
- 引数がなく、何もしないコンストラクタ。コンパイラが自動で用意。
- コンストラクタの簡単化(再利用)
- 既に定義済みのコンストラクタを、他コンストラクタで再利用したい場合、
this()
により利用できる。pp.321-- 必ずコンストラクタの1行目で呼び出す必要がある。
- 既に定義済みのコンストラクタを、他コンストラクタで再利用したい場合、
- カプセル化=隠蔽(実装詳細の隠蔽)
- 直接的な目的: フィールド変数へのアクセスを制限する。
- 例: 年齢入力してほしいのに、マイナス値を入力された場合。
- 直接フィールド変数に年齢を設定するとマイナス値だろうが設定できてしまうが。
- これに対し、フィールド変数設定用のメソッド(後述)を用意しておけば、メソッド内で例外処理が可能。
- 例: 年齢入力してほしいのに、マイナス値を入力された場合。
- 間接的な目的: プログラムを修正に耐えやすくする。(どう実装されてるかは問わず、最低限の使い方だけを提供することで実装変更に耐えやすくする)
- 直接的な目的: フィールド変数へのアクセスを制限する。
- カプセル化の方法
- フィールド変数に private修飾子 を付ける。(他クラスからアクセス出来ないように隠蔽する)
- フィールド変数を参照・設定するための アクセサメソッド(Getter/Setter) を用意する。
- アクセス修飾子の種類
- private: 同一クラス内からだけアクセスできる。
- (修飾子なし)デフォルト: 同じパッケージ内にあればアクセスできる。
- public: 条件なし。自由にアクセスできる。
- コード例3
- カプセル化の例。
//クラス例: Dice.java
public class Dice {
private int val; //カプセル化(14.3節)
private String color; //カプセル化
//コンストラクタ
public Dice(int val){
this.val = val;
}
//コンストラクタのオーバーロード(14.2節)
public Dice(){
play();
}
//カプセル化によりprivate変数への操作を用意。
//アクセサメソッドその1。getter+setter for val.
public int getVal(){ return val; }
public void setVal(int val){ this.val = val; }
//アクセサメソッドその2。getter+setter for color.
public String getColor(){ return color; }
public void setColor(String color){ this.color = color; }
public void play(){
val = (int)(Math.random()*6) + 1;
}
}