クラスとオブジェクト

クラスとは

Javaプログラムを作成する際には、必ずクラスを使用します。

クラスとは、「データ(変数)と処理(メソッド)」の集まりのことを指します。
オブジェクト指向プログラミングの基本的な仕組みを提供するもので、
オブジェクト(=インスタンス)が持つ、フィールド(属性やプロパティ、アトリビュートとも呼ばれます)やメソッドなどを定義します。

今まで作成していたクラス(public static void main(String[] args)が記述されているクラス)は、
どんな処理をするのか、どんなデータを使うのかを記述するための中心となるクラスでした。

クラスは分けて記述することも可能で、「整理されてプログラムを読みやすくする」「作業をファイル単位で分割して開発を平行に進められる」といったメリットがあります。

メソッドの処理を部品とするならば、クラスは部品を集めて出来た機械と考えてみましょう。

クラスの実装

「com.cmps」直下に「classObject」パッケージを作成し、
新規クラスの「Calc」と「ClassObject」を配置、以下のソースを記述しましょう。

Calcクラス
Calcクラスに記述してあるのは、メソッドの単元で取り扱ったメソッドなので解説は省きます。

public class Calc {
    // 足し算をするメソッド
    public static void addition(int num, int fig) {
        int answer = num + fig;
        System.out.println("足し算の結果は" + answer + "です!");
    }

    // 掛け算をするメソッド
    public static void multiplication(int num, int fig) {
        int answer = num * fig;
        System.out.println("掛け算の結果は" + answer + "です!");
    }

    // 文字加工をするメソッド
    public static void characterConversion(String text) {
        String answer = text.trim();
        answer = answer.substring(0, 1).toUpperCase() + answer.substring(1, answer.length() - 1).toLowerCase();
        System.out.println("文字を加工した結果は" + answer + "です!");
    }
}

ClassObjectクラス
Calcクラスのメソッドを呼び出して使用しています。

public class ClassObject {

    public static void main(String[] args) {
        /*
         * クラス内のメソッドを呼び出すサンプル
         */
        Calc.addition(5, 3);

        int num = 3;
        int fig = 15;

        Calc.multiplication(num, fig);

        String word = "こんにちは";
        Calc.characterConversion(word);
    }
}

ClassObjectクラスに注目してください。

他クラスの処理を呼び出すには、以下の定義で実行することが出来ます。

クラス名.メソッド名 (引数) ;

今回の処理ではCalcクラスの各メソッドを呼びたいため、メソッドの手前に「Calc.」と指定して実行したい処理を記載しています。

クラスのインスタンス化

インスタンスとは「クラスを実際に利用可能な状態にしたオブジェクト」を指します。
クラスを「設計図」とするならば、インスタンスは「設計図を基に作成したもの」です。

そのインスタンスを作成する工程のことを、インスタンス化(オブジェクト化)といいます。

Listを使った宣言を行った時にどのように宣言をしていたでしょうか?
以下のような形で宣言していました。
「List<String> list = new ArrayList<String>()」

このような記述がインスタンス化です。
ArrayListはデータの型の一つであると同時に、ArrayListというクラスです。

Listがクラスであると考えた時に注目してほしいポイントが「new」の記載です。
これは「New演算子」といい、クラスからインスタンスを作るときに使う演算子です。

フィールド変数

フィールド変数とは、クラス内で宣言している変数の事です。
クラスブロック内の全処理(全メソッド)内で使用可能です。

これまで変数の宣言は、メソッド内部で行っていました。
そのようなメソッド内部で宣言された変数のことをローカル変数と呼びます。

クラスブロック内の全メソッドで使用可能なフィールド変数と、宣言したメソッド内でのみ使用可能なローカル変数では、動作が異なりますので注意して下さい。

言葉だけで理解するのは難しいかと思いますので、以下のソースコードの判例を見てみましょう。

フィールド変数解説

メインクラスの中に、String型の変数「os」とinteger型の変数「memory」、
startメソッドとfinishメソッドがあります。

「os」と「memory」が、クラスブロック内で宣言されているフィールド変数(メンバ変数)です。属性を宣言している部分をフィールドと呼びます。

フィールド変数には、他のクラスでも変数の値を使えるという特徴があり、
この機能自体は非常に便利ですが、間違ったデータを取得してしまう危険性もあります。
変数を使用できる範囲を調整しないと、あらぬ場所からデータをとってきてしまうリスクがどうしても出てきてしまいます。

使用できる範囲を制限するために、アクセス修飾子を使用します。

アクセス修飾子

アクセス修飾子とは、クラスやそのメンバーに対する「可視性」、つまり「公開範囲」を指定するための修飾子です。
クラスを宣言する際などに「public」の文言を見かけたかと思います。あれが公開範囲を決めるアクセス修飾子です。


アクセス修飾子を適用することで、クラスの内部実装を隠蔽し、データを保護することができます。
データを保護できることで、カプセル化の原則が強化され、ソフトウェアの安全性と保守性が向上できます。

アクセス修飾子にはpublic、protected、privateの3種類がありますが、
「アクセス修飾子を付与しない状態」も可視性の一種と考えられるため、以下の4つに分類されます。

public
publicはクラス・メソッド・変数・その他のメンバに対して設定することができ、すべての場所からアクセス可能です。
publicは、最も制限の少ないアクセスレベルで、プログラムのどの部分からでも自由にアクセスができるため、
APIやライブラリのインターフェースとして使用されることが多いです。

protected
protectedはクラスのメンバに対して設定されます。自クラスおよび同一パッケージ内のクラスと、 自身の子クラスからアクセス可能です。(子クラスについては「継承とオーバーライド」で扱います。)
protectedは、親クラスが提供する機能を拡張して子クラスを作成する際や、
パッケージ内のクラス間での相互作用させたい場合などに役立ちます。

デフォルト(修飾子無し)
アクセス修飾子を指定せずに使用することです。無指定とも言います。
同じパッケージに属する他のクラスからのみアクセス可能です。

private
privateはクラスのメンバに対して設定されます。自分自身が含まれるクラス内からしかアクセスできません。
外部から直接参照や変更が出来ないので、privateには、データの隠蔽・情報の保護・安全性の向上といった利点があります。

表にまとめると以下のようになります。

アクセス可能範囲publicprotectedデフォルトprivate
同じクラス内から
同一パッケージ内のクラスから×
自身の子クラスから××
別パッケージの子クラス以外でも ×××

メンバ

メンバとはクラスに用意した変数やメソッド、コンストラクタの総称です。

その中のフィールド変数とメソッドのメンバについては、
インスタンスメンバ」と「クラスメンバ」の2種類に分類が可能です。

クラスメンバ

インスタンスメンバがオブジェクトに関連付けられていたように、クラスメンバはクラスに関連付けられるメンバのことを言います。

クラスメンバの定義方法

public class クラス名 {
    (アクセス修飾子) static 型名 フィールド変数名 // クラス変数
    …

    (アクセス修飾子) static 戻り値の型 メソッド名(引数) { // クラスメソッド
        …
    }
}

インスタンスメンバと比べ、staticキーワードがついている点が異なります。
staticキーワードが付けられたクラスメンバを「スタティックメンバ(静的メンバ)」とも言います。

staticが付いていなければインスタンスメンバ、staticが付いていればクラスメンバです。

クラスメンバへのアクセス方法

クラス名.クラス変数名;

クラス名.クラスメソッド名(引数…);

クラスメンバへのアクセス方法は「クラス名」の後に「.」をつけてアクセスしたいクラスメンバを記述します。
オブジェクトの生成が必要ない点がポイントになります。

本単元の最初に扱った、Calcクラスのメソッドを呼び出す処理(ClassObjectクラスの記述)がこれにあたります。

インスタンスメンバ

クラス内のインスタンスメンバはオブジェクトが作成されてはじめて、フィールド変数に値を格納できたり、メソッドを呼び出したりすることができます
逆に言えば、オブジェクトを生成しない限りメンバにアクセスができないという性質をもつものがインスタンスメンバになります。
インスタンスメンバは、オブジェクト生成時に、オブジェクトごとに生成されます。

インスタンスメンバの定義方法

public class クラス名 {
    (アクセス修飾子) 型名 フィールド変数 // インスタンス変数
    …

    (アクセス修飾子) 戻り値の型 メソッド名(引数){ // インスタンスメソッド
        …
    }
} 

インスタンス化の方法

//インスタンス化
クラス名 変数名 = new クラス名();

//インスタンス化(宣言と代入を分ける場合)
クラス名 変数名;
変数名 = new クラス名();

インスタンス化の具体的例、およびインスタンスメンバへのアクセス方法については次の「アクセサメソッド(getter・setter)」で詳しく説明します。
※なお、インスタンスメンバへのアクセスについてもクラスメンバと同様変数名.メンバ名のような形で記載をすることも可能ですが、「カプセル化」の概念から一般に推奨されません。
本マニュアルでも、インスタンスメンバにはアクセサメソッドを用意し、アクセサメソッドを介してアクセスします。

インスタンスメンバとクラスメンバの違い

インスタンスメンバとの違いですが、「メモリの保存場所」が異なります。

インスタンスメンバの場合、クラスのインスタンス(オブジェクト)ごとに保存領域が確保されます。
例えば、1つのクラスから5つのインスタンスを作成すれば、
「インスタンスメンバの数×5つ分」の領域が確保されます。

一方、クラスメンバはクラス単位で保存領域が確保されます。
例え複数インスタンスを作成しても、クラスメンバ1つ文の領域のみ確保されます。

オブジェクトごとに異なる値を設定したいのであればインスタンスメンバ、
全てのオブジェクト共通の値として使いたいならクラスメンバで、そのどちらかの目的に応じて使い分けます。

アクセサメソッド(getter・setter)

オブジェクト指向で触れた「カプセル化」を行うことで、フィールド変数への直接的なアクセスを禁止します。
具体的には、フィールド変数自身はprivate(クラス外から操作不可)とし、
フィールド変数の値を設定するメソッド(setterメソッド)と 取得するメソッド(getterメソッド)をpublicで用意し、
フィールド変数にはこれらのメソッドを通してしかアクセスできないようにします。

アクセサメソッドとは、『set○○』『get○○』といったフィールドへのアクセスを仲介する目的で用意されるメソッドのことを言います。

値を直接触れるようにしてしまうと、様々なクラスから呼び出された同じ変数名を使ってプログラムを書くと読みにくさに繋がる事、特定の条件で値を入れたいのに直接値を入れられて予期せぬエラーが発生してしまう事等、様々な問題が発生してしまいます。

そこで、直接クラスの変数を使わずに、メソッドを間接的に配置することでクラス内の変数を書き換える・取得するといった動作を行います。
このクラス内のメソッドを通して 変数を取得・書き換えを行うことをgettersetterとそれぞれ読んでいます。

簡単に言うと、privateになっているフィールド変数を、変更するのが「setter取得するのが「getterです!


事例を見てみましょう。
「com.cmps.classObject」パッケージ内に「Book」クラスを作成し、「ClassObject」・「Book」クラスに以下のソースを記述しましょう。

・Bookクラス

package com.cmps.classObject;

public class Book {
    // インスタンスメンバ
    private int tax;
    private String name;
    
    // 1.getter基本形
    public int getTax() {
        return this.tax;
    }
    // 2.setter基本形
    public void setTax(int tax) {
        this.tax = tax;
    } 
    
    // 1.getter基本形
    public String getName() {
        return this.name;
    }
    // 2.setter基本形
    public void setName(String name) {
        this.name = name;
    }
    
}

・ClassObjectクラスのmainメソッドの続き

// 他のクラスを使用する際は、「new クラス名」でインスタンス化
Book overview = new Book();
        
// setで本の名前を格納
overview.setName("こころ");
overview.setTax(2000);
        
System.out.println("本の名前は" + overview.getName());
System.out.println("本の値段は" + overview.getTax() + "円");

まずは1のgetの基本形から見ていきましょう。
「get」メソッドの宣言時は返却する値が必要なので、メソッドの戻り値には「int」や「String」など返却するデータの型を指定します。

getterを実行すると、this.taxという値をreturnで返却して取得できます。
getterメソッド内に登場する「this」は、クラスが保持しているスコープの変数(ここではオブジェクト「overview」)を使うときに使用します。
つまり「this.tax」は「オブジェクトoverview の tax フィールド」を指し、overview.tax の値(2000)が getTax() の戻り値となります。

次に2のsetの基本形を見てみましょう。
スコープ1の変数の扱いは少し特殊で、メソッド引数の変数名と クラスで使用されている変数名を同じにしても、
thisを付ける事でどちらの変数を使うのかを判断することが出来ます。
setTaxの場合なら「this.tax (クラスが保持している変数) = tax (引数として取得した通常の変数) 」という意味で、インスタンス変数に引数taxを代入する という処理を行っています。

☆eclipse内では変数名にカーソルを当てる(クリックする)と、同じ変数同士が視覚的に示されるので区別の参考にしましょう。

getter・setterのメソッドを作るときは、一般に以下の記載方法で命名するのが慣習になっています。
このように命名を統一すると可読性が上がって読みやすくなります。

「get変数名」「set変数名」

Javaでの推奨の命名方法として、複数の単語が続く時はキャメルケースにします。(単語の切り替わりの最初の文字を大文字にする)
getter、setterでも同様です。
(例)
フィールド名「name」→「getName」「setName」
フィールド名「postCode」→「getPostCode」「setPostCode」

なお、getやsetはよほどの事情がない限りは他のクラスから呼び出せるように
「public ~ get」と、メソッドのフィールド変数を「public」にします。

コンストラクタ

コンストラクタとは

コンストラクタ(constructor:構築者)とは、クラスからオブジェクト(インスタンス)を作成した際に、自動的に実行される特殊なメソッドの事です。メンバ変数を初期化する際などに主に使用します。

特徴としては
・クラス名と全く同じ名前のメソッド
・戻り値が無いので、コンストラクタを作成する時は「void」や「int」「String」等の指定はしないで記載します。
・すべてのクラスに対し、オブジェクト作成時に必ず呼ばれる

コンストラクタの定義は以下の様に記述します。

public class メインクラス名{
    public static void main(String[] args) {   
        //インスタンスの生成
        クラス名 変数名 = new クラス名();    
    }
}

class クラス名{
    //コンストラクタ(インスタンス生成時に実行される)
    public クラス名(){
        初期化処理など
    }
}

コンストラクタは、インスタンス生成時に自動で実行されます。

実際に操作してみましょう。
「com.cmps.classObject」パッケージ内に「Constructor」クラスを作成し、
・ClassObjectクラス、メインメソッド内に以下を記述してください。

// インスタンスの作成
Constructor sample = new Constructor(); // ①

・Constructorクラスには以下を記述してください。

package com.cmps.classObject;

public class Constructor {
    String string = "Hello"; // インスタンス変数 ②
    
    // コンストラクタ
    public Constructor() { // ③
        System.out.println(string); // ④
    }
}

ClassObject.javaの実行結果

Hello

上記の処理の流れとしては以下の通りです。
①メモリに Constructor クラスのインスタンスを確保(オブジェクト sample のためのメモリが確保される)。
②Constructorクラス内にて「String string = “Hello”」が実行され、sample.stringへ「Hello」が代入される。
③コンストラクタが実行され、 public Constructor() が呼ばれる。
④「System.out.println(string);」により、「Hello」が出力される。

このように「オブジェクト化したら必ず実行させたい処理」として設定できます。

コンストラクタの種類

コンストラクタには3種類あります。
① デフォルトコンストラクタ
② 引数なしのコンストラクタ
③ 引数ありのコンストラクタ

さきほど作成したのは ② 引数なしのコンストラクタ です。
③ 引数ありのコンストラクタ を作成してみましょう。
・ClassObjectクラス メインメソッド内に以下を記述してください。

// インスタンス(引数あり)の作成
Constructor sample2 = new Constructor("Hi!");

・Constructorクラス 以下を記述してください。

// コンストラクタ(引数あり)
public Constructor(String string) {
    this.string = string;
    System.out.println(this.string);
}

ClassObject.javaの実行結果

Hi!

いかがでしょうか。引数を渡してオブジェクト化すると同時に、オブジェクト変数を上書きし、出力しています。

なお、同名のメソッドは作れないのでは?と思ったかもしれませんが、これについては次の「メソッドのオーバーロード」で説明します。
③についてはオーバーロードの要件を満たしていれば、いくつでも作成できます。

次に、① デフォルトコンストラクタについて
実はすべてのクラスは、コンストラクタを設定しなかった場合も自動でコンストラクタが用意され実行されています。

マニュアル内で Bookオブジェクトを作成しましたが、Bookクラス内にはコンストラクタを定義していません。しかしインスタンス化は問題なく実行されています。
クラスにコンストラクタを定義していない場合、デフォルトのコンストラクタが用意され実行されているのです。

なお、デフォルトコンストラクタはほとんど何も行いません。(詳細にはsuper(); という親クラス(スーパークラス)のコンストラクタを呼び出す処理が行われていますが、ここでは割愛します。→継承とオーバーライド

メソッドのオーバーロード

クラス内ではフィールド変数、メソッド、コンストラクタといったメンバを定義することが出来ますが、その中でメソッドとコンストラクタは、オーバーロード(多重定義)という機能により、同じ名前で複数定義できる仕組みが備わっています。

オーバーロードとは、引数の数や型を変えた同じ名前のメソッドを複数作ることで実装することです。
ただし、オーバーロードを利用するには以下の様なルールがあります。
・同じ名前でメソッドを定義する
・各メソッドの引数の型・個数・並びが異なるようにする

オーバーロードをする理由ですが、メソッドをオーバーロードすることでインターフェースに一貫性を持たせ、
どのデータ型を渡す場合でも、論理的に整合性のある形でメソッドを呼び出すことができるためです。

同じような機能を持つメソッドであれば引数のデータ型が異なっていても
同じメソッド名を使って呼び出せると便利じゃない?ということです。

・メソッドのオーバーロードの書式

public class クラス名{

    public void メソッド名(String str){ … }
    public void メソッド名(int num){ … }
    public void メソッド名(String str, int num){ … }
    public void メソッド名(int num, String str){ … }

}

・オーバーロードの正しい例

public class Book{

    public void setBook(String name){ … }
    public void setBook(int tax){ … }
    public void setBook(String name, int tax){ … }
    public void setBook(int tax, String name){ … }

}

上の2行は、同じ「setBook」というメソッドですが、引数の型が異なるため別のメソッドとみなされます。
同様に、下の2行も個数や並びが異なるので、すべて別のメソッドとみなされます。

・オーバーロードの間違い例

public class Book{
 
    //「返り値の型」が違うだけでは、オーバーロードにはなりません
    public void setBook(String name){ … } 
    public String setBook(String name){ … }

    // 「仮引数名(name1やtax2など)」が違うだけでは、オーバーロードにはなりません 
    public void setBook(String name1, int tax1){ … }
    public void setBook(String name2, int tax2){ … }

}

上記の例は定義する分には問題ないように思えますが、「呼び出し元で見分けがつかない」点が問題になっています。

最初の2行は、メソッドを呼び出す時に、戻り値の型が違うだけで同じ引数の型同士ではどちらのメソッドを呼び出していいのか見分けがつきません。
戻り値の型はメソッドが呼ばれた後の情報になるので、呼び出し元が見分けるときの情報にはなりません。

あとの2行は、仮引数の名前が違うだけで同じ引数の型、個数同士ではどちらのメソッドを呼び出していいのか見分けがつきません。
引数の名前は呼び出した後に使われる情報なので、これも呼び出し元が見分けるときの情報にはなりません。

オーバーロードの正誤図

シグネチャ
「メソッド名」と「引数の組み合わせ(型・個数・並び)」のことをメソッドの「シグネチャ」といいます。
Javaではこのシグネチャによりメソッドを見分けています。

オーバーロードを試してみましょう
ClassObjectクラス内に以下のソースを記述しましょう。

    public static void main(String[] args){

        //以下はメインメソッド内に追記
        //引数の数がバラバラになっているcalcメソッドを実行してみる
        calc();
        calc(2);
        calc(2,2);
        calc(2,2,2);
    }

    //受け取る引数の数が違うためJava上でどのメソッドを使えばいいのかを判断してくれる。
    public static void calc() {
        int ans = 1 * 1;
        System.out.println("計算(引数1):" + ans);
    }
    public static void calc(int num) {
        int ans = num * 1;  // 2*1
        System.out.println("計算(引数1):"+ans);
    }
    public static void calc(int num,int fig) {
        int ans = num * fig; // 2*2
        System.out.println("計算(引数2):"+ans);
    }
    public static void calc(int num,int fig,int dig) {
        int ans = num * fig * dig;
        System.out.println("計算(引数3):"+ans);
    }

出力結果

計算(引数1):1
計算(引数1):2
計算(引数2):4
計算(引数3):8

次に引数の型がバラバラになっているprintメソッドを実行してみましょう

    public static void main(String[] args){

        //以下はメインメソッド内に追記
        //事前準備
        int test1 = 1;
        String test2 = "1";
        byte test3 = 1;
        float test4 = 1.0f;
       
        // 引数の型がバラバラになっているprintメソッドを実行
        print(test1);
        print(test2);
        print(test3);
        print(test4);
    }

    //引数の型が違っていてもPCはどのメソッドを使うのか判断ができるため、これもOK
    public static void print(int out) {
        System.out.println("出力1:"+out);
    }
    public static void print(String out) {
        System.out.println("出力2:"+out);
    }
    public static void print(byte out) {
        System.out.println("出力3:"+out);
    }
    public static void print(float out) {
        System.out.println("出力4:"+out);
    }

出力結果

出力1:1
出力2:1
出力3:1
出力4:1.0

同じメソッドでありながら、異なる出力結果を確認できたのではないでしょうか。

練習問題

「com.cmps.classObject」直下に「question」パッケージを作成し、
新規クラスの「ClassObjectQuestion」「Login」「Message」を配置、以下のソースを記述しましょう。

・Messageクラス

public class Message {
	/*
	 * 問題① 下記のメッセージ一覧について、staticを使ってクラス変数としてそれぞれ定義してください。
	 * また、変更予定がない定数として、finalキーワードもつけること。
	 * (下記は 変数名:変数の値 という形で記載しています)
         * ※ヒント 「クラスメンバの定義」を参照
	 * ・ME001:ログイン認証開始
	 * ・ME002:アカウント確認を実行
	 * ・ME003:アカウントに問題はありませんでした
	 * ・ME004:パスワード確認を実行
	 * ・ME005:パスワードに問題はありませんでした
	 * ・ME006:ログインに成功
	 * ・EE001:存在しないアカウントです
	 * ・EE002:パスワードに誤りがあります
	 * ・EE003:ログインに失敗しました
	 * 	 */
}

・Login

public class Login {
	private static Map<String, String> map;
	private static final String[] REGULAR_ACCOUNT = { "student", "teacher" };
	private static final String[] REGULAR_PASSWORD = { "1234", "1111" };

	private String account; // アカウント
	private String password; // パスワード

	/*
	 * 問題② ログインを実行するためのコンストラクタ(クラス名は「Login」)を作成してください。
	 * 引数は無しで、上で作成した変数「アカウント」と「パスワード」に空文字("")を代入してください
	 * また、initialization()メソッドを実行してください
	 */


	/*
	 * 問題③ ログインを実行するためのコンストラクタ(クラス名は「Login」)をオーバーロードして作成してください。
	 * 引数はString accountとString passwordとし、インスタンス変数に格納しましょう。
	 * また、問②同様initialization()メソッドを実行してください
	 * ※ヒント thisを使ってインスタンス変数に格納しましょう。
	 */


	/*
	 * 問題④ インスタンス変数であるアカウント、パスワードについてのgetter・setterメソッドを作成してください。
	 */


	// ログインを確認するためのメソッド(そのままコピペでOK)
	public void loginCheck() {
		// メッセージ出力
		System.out.println(Message.ME001);

		// アカウント、パスワードが正しく登録できているかを確認するためのboolean変数
		boolean accountBoolean;
		boolean passwordBoolean;

		// アカウント、パスワードを確認する
		accountBoolean = checkAccount(this.account);
		if (accountBoolean) {
			passwordBoolean = checkPassword(this.password);
		} else {
			passwordBoolean = false;
		}
		// ログインが完了したかを確認するメソッド
		if (accountBoolean && passwordBoolean) {
			System.out.println(Message.ME006);
		} else {
			System.out.println(Message.EE003);
		}
	}

	/*
	 * 問題⑤アカウントがmapの中に存在するかを確認する「checkAccount」メソッドを作成してください。
	 * メソッド内でME002、ME003、EE001を使って処理の開始、処理した結果(true,false)を出力してください。
	 * ヒント
	 * ・Mapはキー取得を行い、存在しない場合はnullを返却します。
	 * ・mapに登録されたアカウント名をキーとして、該当するパスワードを取得します。
	 */
	private boolean checkAccount(String account) {
		System.out.println(Message.ME002);
		String content = map.get(account); // mapに登録されたアカウント名をキーとして、該当するパスワードを取得します。

		// ↓以下に記述↓

	}

	/*
	 * 問題⑥パスワードが入力されたアカウントに対して、正しいパスワードが入力されているかを判定する
	 * 「checkPassword」メソッドを以下の条件で作成してください。
	 * ・パスワードがあっている場合はtrue、パスワードが間違っている場合はfalseを返却すること
	 * ・ME004、ME005、EE002を使って処理の開始、処理した結果を出力してください。
	 * ヒント、クラスが保持しているアカウントを使ってパスワードを取得すると良いでしょう。
	 * 
	 */
	private boolean checkPassword(String password) {
		System.out.println(Message.ME004);
		String checkPassword = map.get(this.account);

		// クラス変数に紐づいたパスワードをmapから取得、引数passwordと比較。
		// ↓以下に記述↓

	}

	// ログイン出来るパスワードを予め実行するメソッド
	private static void initialization() {
		map = new HashMap<String, String>();
		map.put(REGULAR_ACCOUNT[0], REGULAR_PASSWORD[0]);
		map.put(REGULAR_ACCOUNT[1], REGULAR_PASSWORD[1]);
	}
}

・ClassObjectQuestionクラス

public class ClassObjectQuestion {
	public static void main(String[] args) {
		// 問題① Messageクラスにて作成したメッセージをコンソール上へ出力してみましょう。
		// ヒント 「クラスメンバへのアクセス方法」を参照
		System.out.println("問1");

		
		// 変数「account」と「password」を作成
		// これらの変数に格納された値を判定します。
		String account = "student";
		String password = "1234";
		
		//インスタンス化、コンストラクタで自動実行
		Login human = new Login(account,password);
		
		//ログインが出来るかを確認する。
		human.loginCheck();
		
		//アカウント名を確認する(○○部分は問4で作成したメソッド)
		System.out.println("アカウント名は"+human.○○()+"です");

	}
}

問題⑥まで記述出来たら、メインメソッド内の

String account = "student";
String password = "124";

これらの変数の値を変えて、
Loginクラスで定義されている配列「REGULAR_ACCOUNT」「REGULAR_PASSWORD」に格納されている値と一致した場合、しなかった場合でログインが成功するか見てみましょう。

練習問題のヒント
問2
引数無しのコンストラクタを作成します。

問3
問2とクラス名は同じですが「引数付きのコンストラクタ」ということなので
public Login() の()内にそれぞれ指定された引数を設定します。
そして、インスタンス変数であるaccountとpasswordへそれぞれ引数を格納しましょう。

問5
「アカウントがmapの中に存在するかを確認」するにはif文を使います。
取得したパスワードが格納された変数「content」が存在するかを判定しましょう。

content、つまりアカウントが存在すればtrueを返し、ME003のメッセージを出力、
そうでなければ、falseを返しEE001を出力させます。

問6
問5同様、if文を使ってパスワードが正しい場合とそうでない場合で条件分岐させます。
具体的には「passwordがnullでないこと」かつ「passwordとcheckPasswordが等しいこと」を判定します。

タイトルとURLをコピーしました