クラス(class)

コンストラクタ(Constructors)

Triangleクラスはassign()メソッドを用いて,そのオブジェクトの初期化を行っています.しかし,オブジェクトが宣言されたときに,初期化するほうがより自然です.そこで,Javaではクラスオブジェクトに対して,初期化が行えるようにコンストラクタメソッドを用意しています.

コンストラクタは特殊なメソッドで,オブジェクトが宣言されると自動的に呼び出されます.つまり,Triangle t = new Triangle()で,Triangleクラスのオブジェクトtが作成されますが,実はコンストラクタが自動的に呼び出されたのです.コンストラクタは,クラスのオブジェクトを作る関数です.そのため,コンストラクタはクラスと同じ名前を取ります.

例題 6..1   三角形クラス
\framebox{
\begin{minipage}{13.65cm}
{\rm 底辺18,高さ24.5の三角形の面積を求めるプログラムをコンストラクタを用いて作成しなさい.}
\end{minipage}}

解答

  1. Triangleクラスの宣言を行います.
  2. コンストラクタの定義を行います.コンストラクタの定義は
    public コンストラクタ名(型 引数)

    {
    }
    で行います.
  3. メソッドの定義を行います.メソッドの定義は
    戻り値のデータ型 メソッド名()
    {
    }
    で行います.
  4. 最後にmainメソッドでTriangleクラス型のオブジェクトを作り,三角形の面積を求めます.

class TriangleConstructor
{
  private double base, height;
  public TriangleConstructor(double b, double h)
  {
    base = b;
    height = h;
  }
  public double area()
  {
    return base*height/2;
  }
  public void display()
  {
    System.out.println("底辺" + base + "高さ" + height + "の三角形の面積は" + area());
  }
  public static void main(String[] args)
  {
    Triangle t = new Triangle(18,24.5);
    t.display();
  }
}

実行結果

\begin{figure}\centering
\includegraphics[width=7.8cm]{JAVAFIG/TriangleConstructor.eps}
\end{figure}

Triangle t = new Triangle(18,24.5)により,baseとheightを持つオブジェクトtが作成され,18と24.5がそれぞれbaseとheightに渡されます.

練習問題 6..1  
上の例題で,底辺が10,高さが20の三角形オブジェクトobj2をコンストラクタを用いて作成し,その面積を求めなさい.

ここで,Triangleクラスとそのインスタンス化されたオブジェクトの関係を図で表すと次のようになります.

\begin{figure}\centering\includegraphics[width=10.6cm]{CPPPIC/fig10-2.eps}
\end{figure}
ここで,クラスは丸角矩形で表されメソッドを含んでいます.それぞれのメソッドはthisポインタを保持しています.thisポインタは,呼んでいるオブジェクトを指しています.この図は,上のプログラムの最後の行t.display()で何が起きているのかを表しています.つまり,オブジェクトtがdisplay()メソッドを呼び出しています.その瞬間,コンストラクタのthisポインタは呼ばれていないのでNULLです.

クラスは1つ以上のコンストラクタを持つことができます.

メソッドへのオブジェクトの引渡し

メソッドに引数としてデータを渡すのと同じように,オブジェクトを引数として渡すことができます.それには,渡すオブジェクトの型を使用してメソッドの仮引数を宣言します.

例題 6..2   三角形クラス
\framebox{
\begin{minipage}{13.65cm}
{\rm 底辺18,高さ24.5の三角形の面積とメソッドを利用して面積の2乗を求めるプログラムをコンストラクタを用いて作成しなさい.}
\end{minipage}}

解答 面積の2乗を求める関数をdouble sqArea();とします.

class SqAreaOfTriangle
{
  private double base, height;
  public SqAreaOfTriangle(double b, double h)
  {
    base = b;
    height = h;
  }
  public double sqArea()
  {
    double a = base*height/2;
    return a*a;
  }
  public void display()
  {
    System.out.println("底辺" + base + "高さ" + height + "の三角形の面積の2乗は" + sqArea());
  }
  public static void main(String[] args)
  {
    SqAreaOfTriangle t = new SqAreaOfTriangle(18,24.5);
    t.display();
  }
}

実行結果

\begin{figure}\centering
\includegraphics[width=10.3cm]{JAVAFIG/SqAreaOfTriangle.eps}
\end{figure}

クラス変数とクラスメソッド

すでに述べたように,クラスは「フィールド」と「メソッド」というい2種類のメンバを持っています.このフィールドとメソッドは厳密にはそれぞれ二つの性格のものに分けられ,計4つに分類されます.

ここでは,特殊なフィールド変数について学びます.Triangleクラスのオブジェクトを作成すると,それぞれのオブジェクトのbaseやheightに値を代入したり出力したりすることができます.つまり,各オブジェクトごとにフィールド変数に値を格納することができます.このことを,フィールド変数base, heightはオブジェクトに関連付けられているといい,このフィールド変数をインスタンス変数といいます.また,display()メソッドも,オブジェクトを作成することによって,呼び出すことができます.このメソッドもオブジェクトに関連付けられているといい,このメソッドをインスタンスメソッドといいます.このように通常は,メンバはオブジェクトに関連付けられています.

ところが,クラスはオブジェクトに関連付けられていないメンバを持つことができます.これをクラス全体に関連付けられているといいます.クラスに関連付けられているフィールド変数をクラス変数(静的変数)といい,クラスに関連付けられているメソッドをクラスメソッドといいます.

クラス変数はスタティック(static)という記憶クラス指定子を付けて宣言します.その構文は次のようになります.
class StaticX
{
private static int n; // nをクラス変数として宣言
}
これにより,クラス変数には,次のような2通りのアクセスの仕方が可能になります.

StaticX obj = new StaticX();
obj.n = 100;

または,
StaticX.n = 100;

例題 6..3   クラス変数
\framebox{
\begin{minipage}{13.65cm}
{\rm TriangleクラスにTriangleオブジェクトの数を数えるためのクラス...
...tを加える.Triangleオブジェクトが生成されるとカウンタは増え,Triangleオブジェクトが消滅するとカウンタは減る.}
\end{minipage}}

class StaticField
{
  private static int count = 0;
  public StaticField()
  {
    ++count;
  }
  public static void main(String[] args)
  {
    StaticField t = new StaticField();
    StaticField u = new StaticField();
    System.out.println("StaticFieldが" + t.count + "個あります");
    StaticField v = new StaticField();
    System.out.println("StaticFieldが" + t.count + "個あります");
  }
}

実行結果

\begin{figure}\centering
\includegraphics[width=7.8cm]{JAVAFIG/StaticField.eps}
\end{figure}

クラスメソッド(Class Methods)

クラス変数が,クラス名.フィールド変数の形で用いることができたように,メソッドにも,クラス名.メソッド名()の形で用いたほうが便利なものがあります.例えば,数学関係の処理を行うsin()メソッドがインスタンスメソッドである場合,sin()メソッドを呼び出すには,Mathクラスのオブジェクトを次のようにして生成しなければなりません.
Math m = new Math();
double d = m.sin(1.2);

この手続きは面倒です.というのも生成されたMathオブジェクトmは,sin()の計算に何の関与もしません.sin()メソッドに必要なデータはパラメターとして渡され計算結果はメソッドの戻り値として呼び出し元に返されます.クラスのインスタンスを作成したとしても,メソッドの呼び出し以外まったく必要のないものです.これを解決するため,staticキーワードを使用して,メソッドをクラスメソッドとして定義します.

クラスメソッドを呼び出すには,
クラス名.メソッド名(引数リスト);
の形をとります.

例題 6..4   クラスメソッド
\framebox{
\begin{minipage}{13.65cm}
{\rm クラスメソッドを用いて上の例題を書き直せ.}
\end{minipage}}

class StaticMethod
{
  private static int count = 0;
  public StaticMethod()
  {
    ++count;
  }
  private static int num()
  {
    return count;
  }
\hspace{1cm} public static void main(String[] args)
  {
    StaticMethod t = new StaticMethod();
    StaticMethod u = new StaticMethod();
    System.out.println("StaticMethodが" + StaticMethod.num() + "個あります");
    StaticMethod v = new StaticMethod();
    System.out.println("StaticMethodが" + StaticMethod.num() + "個あります");
  }
}

実行結果

\begin{figure}\centering
\includegraphics[width=7.4cm]{JAVAFIG/StaticMethod.eps}
\end{figure}

確認問題 6..1  

1. クラスの公開メンバと非公開メンバとの違いを説明しなさい.

2. クラスメソッドとインスタンスメソッドとの違いを説明しなさい.

3. ディフォルトコンストラクタとそれ以外のコンストラクタとの違いを説明しなさい.

4. コンストラクタにはどんな名前を付けることができるか.

6. 1つのクラスには何個のコンストラクタとディストラクタを含むことができるか.

演習問題 6..1  

1. 空間上の点(x,y,z)からなるPointクラスを作成しなさい.ただし,このクラスは,ディフォルトコンストラクタ,点の座標を負にするnegate()関数,距離を表すnorm()関数,そして表示のためのprint()関数を含むとします.

2. 整数のスタックのStackクラスを作成しなさい.ディフォルトコンストラクタ,ディストラクタ,push(), pop(), isEmpty(), isFull()関数を含むものとします.

\begin{figure}\includegraphics[width=5.7cm]{CPPPIC/stack.eps}
\end{figure}