電話クラスを考える
Javaはオブジェクト指向言語です。オブジェクト指向では現実社会の実態を分析して、クラスというオブジェクトの設計図を考えていきます。皆さん電話というと携帯電話を思い浮かべてしまうかもしれませんが、今回は単純な「電話」を考えてみます。
先ずはクラス名を決めますが、今回は単純に「 Phone 」としてみます。 Javaでは慣習として、クラス名の先頭は大文字にします。 小文字でもコンパイルエラーにはなりませんが、クラス名の先頭は大文字にすることを推奨します。
これまでの情報でクラスを定義すると以下のようになります。
class Phone{
}
まだ何もありませんね。。。
次以降で徐々に肉付けしていきます。
属性(プロパティ)を考える
次にこの電話クラスが持つべき情報を考えます。ここで大事なのは「 持つべき」ということです。
そのクラスが持つべき属性ではない属性を持たせてしまうと、それに必要な操作を追加し、、、 と本来のクラスの責務(役割)から外れたクラスになってしまいます。その情報はどのクラスが保持するべきかということを考えることになります。
電話ということで、まず以下のような属性が思い浮かびました
これを前回作成したクラスに追加すると以下のようになります。
class Phone{
private String telNo;
private String usrName;
}
このクラスのプロパティ(属性)として、電話番号(telNo)と使用者(usrName)が記述されています。しかし、これらのプロパティはアクセス修飾子 private として記述しているため、このクラス以外から直接アクセスすることは出来ません。
このように privateでプロパティを宣言しておけば外部のクラスからこのプロパティを勝手に書き換えることが出来なくなります。これによりプログラマが意図しないところで値が変わってしまうことを防ぐことが出来るのです。このように外部からアクセスできる属性を制限することを カプセル化と言います。
しかしまだ全然クラスらしくないですね、、、
では次に進みましょう。
操作(メソッド)を考える
今度は電話クラスの操作(メソッド)を考えてみます。 メソッドとはそのオブジェクトが行える動作であり、静的なメソッド(後述)以外はインスタンスメソッドと呼ばれ、オブジェクトに結びつけられており、そのオブジェクトに対して作用します。
電話ということで、まず以下のような機能が思い浮かびました
これを前回作成したクラスに追加すると以下のようになります。
class Phone{
private String telNo;
private String usrName;
// 電話を掛ける
public void outgoingCall(String callNo){
System.out.println(usrName + "が" + callNo + "へ電話を掛けます。");
}
// 電話を受ける
public void incomingCall(){
System.out.println(usrName + "が着信しました。");
}
}
[ メソッドに指定できる修飾子 ]
| 修飾子 |
動作 |
| public |
全ての場所からアクセス可能。 |
| protected |
同じパッケージ及び継承するサブクラスからしかアクセスできない。 |
| 記述なし |
何も指定しない場合はパッケージ・アクセスとも言われ、 同じパッケージに属するクラス内からしかアクセスできない。 |
| abstract |
抽象メソッドと呼ばれ、サブクラスによってこのメソッドを実装させる。 |
| static |
静的メソッドと呼ばれ、インスタンスではなくクラスに属するメソッド。 |
| final |
拡張できないメソッド。 |
|
アクセスメソッド
プロパティの宣言の時に privateで宣言したプロパティは外部からアクセスすることが出来ないので、カプセル化を実現していると説明しましたが、どうしてもそのプロパティを外部のクラスから使用するケースが出てきます。
アクセス修飾子を publicへ変更すれば外部のクラスからアクセスすることが出来るようになりますが、それでも読み込みは出来るが書き込みは出来ないと言った制限は行えません。 一般的に Javaではプロパティを公開する際に アクセスメソッドと呼ぶメソッドを用意し、それを介して属性にアクセスを行います。
class Phone{
private String telNo;
private String usrName;
// 電話を掛ける
public void outgoingCall(String callNo){
System.out.println(usrName + "が" + callNo + "へ電話を掛けます。");
}
// 電話を受ける
public void incomingCall(){
System.out.println(usrName + "が着信しました。");
}
// telNoへのアクセスメソッド
public String getTelNo(){
return telNo;
}
public void setTelNo(String pTelNo){
telNo = pTelNo;
}
// usrNameへのアクセスメソッド
public String getUsrName(){
return usrName;
}
public void setUsrName(String pUsrName){
usrName = pUsrName;
}
}
上記サンプルでオレンジに記述した部分がアクセスメソッドです。属性を呼び出す getXXXXは getter(ゲッター)と呼ばれ、属性をセットする setXXXXは setter(セッター)と呼ばれます。慣習として、getterは get属性名と、setterは set属性名とします。
getterのみを記述すればその属性は読み取り専用となりますし、setterにその属性が保持できるデータの範囲を確認してから値を書き換えるということもできるようになります。
電話クラスを使用する
では最後にこれまでに作成した電話クラスを使用してみます。
class Example07_01{
public static void main(String[] args){
// Phoneのインスタンスを生成する
Phone phone1 = new Phone();
Phone phone2 = new Phone();
// phone1に値をセット
phone1.setTelNo("03-xxxx-xxxx");
phone1.setUsrName("木村さん");
// phone2に値をセット
phone2.setTelNo("045-xxx-xxxx");
phone2.setUsrName("佐藤さん");
// インスタンスのメソッドを使用
phone1.outgoingCall("090-xxxx-xxxx");
phone2.outgoingCall("090-xxxx-xxxx");
phone1.incomingCall();
phone2.incomingCall();
}
}
[ 実行結果 ]
木村さんが090-xxxx-xxxxへ電話を掛けます。
佐藤さんが090-xxxx-xxxxへ電話を掛けます。
木村さんが着信しました。
佐藤さんが着信しました。
少しはプログラムらしいものが出来上がりました。
先ず newキーワードを使用してクラスの実体を生成します。new キーワードによりオブジェクトはそれぞれの別々のメモリ空間に生成されるので、phone1と phone2は別のプロパティ値を持つことになります。
outgoingCall() メソッド、incomingCall() メソッドの実行結果を確認してみます。 phone1.outgoingCall("090-xxxx-xxxx"); を実行すると 「木村さんが090-xxxx-xxxxへ電話を掛けます。」と出力されています。 これは、phone1オブジェクトのプロパティに 「telNo」と「usrName」が格納されているからです。
|