03-1: クラスプログラミング
いままで
- メインメソッド内のプログラミング
- メソッドプログラミング
をやってきました。
いよいよ、クラスプログラミングです。
クラスプログラミングは、今まで作成していたクラス同士を横断させて、利用するものです。
インスタンスの作成方法は、2章3節のインスタンスメソッドの回で説明しました。本節では、
- クラスの書き方
- コンストラクタの意味
- インスタンスの生成とstaticについて
等を見ていきます。
早速見ていきましょう。下記は、Hello.java
の中身です。ファイルは単一です。アクセス修飾子に注意してください。
// Hello.java
import java.io.*;
////////////////////////////////////////////////
// クラスプログラミングのためのサンプルクラス
// HelloPrintクラス
class HelloPrint {
// <----- ここにコンストラクタ(後述)が隠れている。------>
void println(){
System.out.println("Hello, World!");
}
void println(String name){
System.out.println("Hello, " + name);
}
}
// Personクラス
class Person{
// インデントは、非常に大事だが、
// 書き方によっては、下記のようにワザとずらして可読性を高めているものもある。
// ただし、Pythonなどのインデントで構造を制御している場合は不可。
// 大学の課題などで、このような書き方をした場合、担当教員によっては注意を受けるかも。
static int sumPerson = 0; // <==== STATICなので、インスタンス同士で値が共有される。
private int numPerson;
private int type; // 後述のSetter/Getterを使うなら、アクセス制限をPrivate(自クラスONLY)にする
priate String name;
/*
* クラス名と同じ名前のメソッドのようなものを「コンストラクタ」という。
* コンストラクタの特徴として
* - 返り値の指定などがないこと
* - インスタンス変数への代入
* などが見られる。
* コンストラクタは、インスタンスを作成する際(例: new String()みたいな際)に呼び出される。
* 上記HelloPrintクラスでは、コンストラクタを明記していない。この場合は、デフォルトコンストラクタが呼び出される。
* デフォルトコンストラクタは、別のクラスからの継承(別章で説明します)などがない限り、何も処理が書いていない。
*/
Person(){
this.numPerson = ++sumPerson; //インクリメントと同時に変数に代入する。前置記法はこんな感じに使う。
this.type = 1;
this.name = "no name";
System.out.println("Born a Person - " + this.name); // DEBUG用
}
// コンストラクタもオーバーロードできる。
Person(String name){
this.numPerson = ++sumPerson;
this.type = 2;
this.name = name;
System.out.println("Born a Person - " + this.name); // DEBUG用
}
/*
* 下記をSetter(セッター)やGetter(ゲッター)という。
* これらは、値をセット(代入)したりゲット(取得)したりするためだけのメソッドである。
* 例えば、名簿を管理する「Member」というクラスがあったときに、名簿情報に関する変数を
* 直接他のクラスから触る、つまり値の処理の記述を他のクラスに書くのは、リスクがある(生のデータをそのまま弄る)
* SetterやGetterを使って、「Member」クラス内のメソッドに代入や取得を委任することによって、安全性が増す。
* また、名簿に関する代入や取得の「機能」をMember...名簿クラスに集約することによって、設計もシンプルになる。
* これは、APIなどの概念に近い。
*/
void setName(String name){
this.name = name; //thisは自分自身という意味です。ここではクラスインスタンスを示します。
/*
この場合、
左辺がクラスインスタンスに紐付けられたインスタンス変数のnameで、
右辺が引数で定義されたローカル変数のnameになります。
*/
}
// 言語によっては、こういう書き方もある。
String getName(){ return name;}
int getType(){ return this.type;}
int getNumPerson(){ return this.numPerson;}
//////////////////////////////////////////////////////
// STATIC変数の場合は、メソッドをインスタンス化する必要がないので、STATICメソッドで良い。
static int getSumPerson(){
return sumPerson;
/* sumPersonはSTATIC変数です。インスタンス変数ではないので、thisをつけることはできません。*/
}
//////////////////////////////////////////////////////////////////////////////
// 注意しなければいけないこととして、getやsetは単に代入や取得をするものであるべきということ。
// 例えば、メソッドがgetNameで、this.nameが`John Smith`なのに、`John_Smith`が返ってきてはいけない。
// この場合は、`getEscapedBrankName`など、それに合ったメソッド名を定義するべきである。
// SetterやGetterと似たようなものとして、is~などがある。is~はXXはYYである。というbooleanを返す。
boolean isMatchedName(String name){
return name.equals(this.name);
}
}
// 以下がメインの処理
public class Hello{
public static void main(String[] args) throws IOException{
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
System.out.println("==========================================");
// HelloPrintクラスのインスタンスを生成する。
System.out.println("Code 01: HelloWorld");
HelloPrint hp = new HelloPrint(); // インスタンス生成
hp.println();
hp.println("Wayne!");
hp.println("Lain!");
System.out.println("==========================================");
System.out.println("Code 02: Make a Person.");
while(true){
System.out.print("plz new name(or quit): ");
String input = buf.readLine();
if(input.equals("quit")) break;
Person man;
if(input.equals("")){
man = new Person(); // Person(引数なし)インスタンス生成
}else{
man = new Person(input); // Person(引数あり)インスタンス生成
}
System.out.println("======= GET INFORMATION =======");
System.out.println("man type: "+ man.getType()); //メソッドを利用してみる。
System.out.println("man name: "+ man.getName());
System.out.println("you are " + man.getNumPerson() + " person.");
// STATICメソッドへのアクセスは、インスタンスを介さず、クラス名で直接アクセスすることを推奨。
System.out.println("SUM: " + Person.getSumPerson());
System.out.println("SUM(FromIns): " + man.getSumPerson()); // <--- つまりコレ非推奨。
System.out.println("===============================");
}
}
}
最終更新日: 2021年4月30日