クラスとインスタンス

クラス


オブジェクトの話で「人間」オブジェクトを作成しました。

それでは、「山田」と「鈴木」オブジェクトを作成したらどうなるでしょうか?

//「山田」オブジェクト作成
let yamada = { 
    name: 'yamada',
    height: 170,
    weight: 60,
    gender: "男",
    age: 30,
}
//「鈴木」オブジェクト作成
let suzuki = {
    name: 'suzuki',
    height: 180,
    weight: 70,
    gender: "男",
    age: 35,
}

書き方自体はこれで問題ないのですが、クラスというものを使った書き方があります。

クラス、インスタンスについて


※ちょっとややこしい内容ですが、下の方で解説していくので、とりあえずサラッと読んで見てください

<クラスとインスタンスについて>

家や車を作る時も、いきなり作り始めたりしませんよね。
まず設計図を作る作業からです。

プログラミングではこの設計図のことを「クラス」と呼びます。
そして、その設計図を元に実体(家や車)を作ります。
プログラミングではこの実体を作り出すことを「 インスタンス化 」と呼びます。

<ポイント>
・クラス(設計図)を作る
・クラスを元に実体を作る(インスタンス化)

クラスとインスタンス(イメージ)



クラスはよく「 設計図 」とも言われます。
まず、テンプレートとなる設計図(クラス)を用意します。
このクラスは「名前」「年齢」「身長」「体重」という情報を持っていますが、
具体的な中身はまだ空っぽです。
言い換えると、中身のデータが空だからこそ、みんなが使い回すことができるといった感じです。


設計図を見ながら人間を作っていきたいのですが、みんな同じ一つの設計図を見ています。
みんなの物なので、使用する時はコピーしてあげる必要があります(インスタンス化)

イメージ的には、この「スマホで写真を撮る」というのが「 インスタンス化 」になります。
写真で撮ってしまえば、設計書と全く同じ物を作り出すことができますよね。
空のものをコピーできたので、後は自分の入れたいデータを入れていけば一つの「人間オブジェクト」の完成です。

クラスはただの設計図で、それはインスタンス化しなければ使うことができません。
クラス自体には値が入っていないので、インスタンス化(コピー)したものに値を入れて使っていくイメージです

「スマホで写真を撮る」=「インスタンス化」というのは、あくまでイメージを掴むための一つの例として参考にしてみてください。
厳密には 「クラスをインスタンス化して、実体を作り出す」 という考え方をするので覚えておいてください。

ソースコードで確認(クラスの宣言、インスタンス化)


それでは、ここまでの話をソースコードで確認していきましょう。

クラス(設計図)の定義の仕方は class クラス名 {} で表します。
今までに何度も出てきた「クラスをインスタンス化(コピー)する」というのは、 new クラス名(); と表します。
以下のようなコードになります。

//Humanクラスを作成
class Human {
    
}
//Humanクラスをインスタンス化して、yamadaを作成
let yamada = new Human();

よく見ると、インスタンス化した後に yamada という変数に代入しています。
これは例えば、パソコンで何かの画像をコピーしたりダウンロードした時に行う 「名前をつけて保存する」 のようなイメージです。
名前をつけて保存したら、今後はその名前でデータを扱っていくことができますよね。

ソースコードで確認(コンストラクタで値をセット)


クラスを作成した時点では、具体的な値は空のままでした。

では、いつどのようにして値を入れるのでしょうか…?答えは、
「 クラスをインスタンス化した時に コンストラクタ でセットする」です。
コンストラクタとは 「クラスがインスタンス化された時に、一番最初に自動で実行される関数」 で constructor() {} で表します。

タイミングで言うと、 new Human(); とした瞬間ですね。
この () のなかに ('yamada') と値を入れてあげると「yamada」をセットする準備ができます。
ついでに年齢も渡してあげましょう。カンマ区切りで並べていくだけです。

//Humanクラスを作成
class Human {
    //コンストラクタ (yamadaと25という値を受け取るための処理をこれから書いていきます)
    constructor() {
        
    }
}
//Humanクラスをインスタンス化
let yamada = new Human('yamada', 25);

「yamada」と「25」の準備ができたので値がセットできるかと思いきや、よく見ると設計書であるクラス側で値を受け取る記述がありません。
コンストラクタで、受け取る準備をしてあげればOKです。

<コンストラクタで値を受け取る手順>

まず、 constructor(name, age) のように () の中に適当な変数を用意します。
こうすると、 new Human('yamada', 25); で渡された値(yamadaと25)を受け取って処理の中で使用できるようになります。

class Human {
    constructor(name, age) {

    }
}


使う変数を受け取ったら、いよいよセットしていきます。
「このクラスから作られたインスタンス」をthisというキーワードを使って表現します。

右辺の「 name 」は constructor(name, ...) のnameのことです。
それを左辺の this.name に入れて、このクラスで使用可能な状態にします。

this.name = name は「 受け取ったname(右辺)をこのクラスのname(左辺)に代入して使える状態にする 」という意味です。

class Human {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
}

中身をみてみましょう。
インスタンス化して yamada という変数に入れたので、
yamada.name とすればアクセスできます。

<完成形>

class Human {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
}
let yamada = new Human('yamada', 20);
console.log(yamada.name);

ブラウザを更新してConsoleに「yamada」と出力されていれば成功です。

それでは、インスタンス化して、コンストラクタで値をセットするまでの流れを確認しておくと以下のようになります。

クラスを使うメリット


これまで、クラスとインスタンスを見てきました。
では最後に、クラスを使うと何が便利なのかという点について見ていきます。

<クラスを使うメリット>
クラスを作成した時、具体的な値は空にして作りました。
「 いったん空のテンプレートを作って、インスタンス化する時に具体的な値をセットする 」
という方法を取れば、 new クラス名(); とするだけで、いくつでもオブジェクトを作成することができます。
先ほど、一番上で以下のように「山田」と「鈴木」オブジェクトを作成しましたね。

//「山田」オブジェクト作成
let yamada = { 
    name: 'yamada',
    height: 170,
    weight: 60,
    gender: "男",
    age: 30,
}
//「鈴木」オブジェクト作成
let suzuki = {
    name: 'suzuki',
    height: 180,
    weight: 70,
    gender: "男",
    age: 35,
}

しかし、クラスを使えば以下のように書き換えられます。

//Humanクラスを作成
class Human {
    constructor(name, height, weight, gender, age) {
        //受け取った値をこのクラスで使えるようにしています。
        this.name = name;
        this.height = height;
        this.weight = weight;
        this.gender = gender;
        this.age = age;
    }
}
//「山田」オブジェクト作成
let yamada = new Human('yamada', 170, 60, '男', 30);
//「鈴木」オブジェクト作成
let suzuki = new Human('suzuki', 180, 70, '男', 35);

クラスの処理も書いているので、ちょっと長いコードに見えますが、
このクラスを元にインスタンスオブジェクトを作れば「 身長の変数の書き忘れた! 」などという自体を防ぐことができます。
コードがスッキリ見やすく管理できて、変更にも強くなります。

さらに、クラスには関数も書くことができます。
作成したオブジェクト一つ一つに関数を書かなくても、インスタンス化すれば設計書(クラス)に書いてある関数を使うことができるようになります。

クラス内で関数を使用する


JavaScriptで「関数」というと、 function 関数名() {} の形で書きます。
例えば、Humanクラスに「歩きました」と出力する walk という関数を作るとします。

ソースコードで言うと以下のようになるはずですが…

function walk() {
    console.log('歩きました');
}

クラスの中に関数を書きたい時は、少し形が異なって、 function が必要なくなります。
(この場合、正確にはメソッドと呼び方が変わるのですが、関数とメソッドの違いについては、余裕があれば次の説明をご覧ください 関数とメソッドの違い

したがって、関数は以下のように書けばOKです。
実行の方法は、インスタンス化した変数(今回だと yamada )に関数名( walk(); )をドットで繋いで書きます。
下のコードの一番したの行ですね。

//Humanクラスを作成
class Human {

    //コンストラクタ
    constructor(name, height, weight, gender, age) {
        this.name = name;
        this.aheightge = height;
        this.weight = weight;
        this.gender = gender;
        this.age = age;
    }

    //歩くメソッド(関数)作成
    walk() {
        console.log('歩きました');
    }
}
//「山田」オブジェクト作成
let yamada = new Human('yamada', 170, 60, '男', 30);
yamada.walk();

せっかくなので、引数で渡した値を使ってみましょう。
「このクラスの〇〇」と指定したいのでthisというキーワードを使って書きます。
+ で繋いでもいいのですが、見づらくなるのでテンプレートリテラルを使って表現しています。

//Humanクラスを作成
class Human {

    //コンストラクタ
    constructor(name, height, weight, gender, age) {
        this.name = name;
        this.height = height;
        this.weight = weight;
        this.gender = gender;
        this.age = age;
    }

    //歩くメソッド(関数)作成
    walk() {
        console.log(`身長${this.height}cm、体重${this.weight}kg、${this.name}という${this.gender}が歩きました`);
    }
}
//「山田」オブジェクト作成
let yamada = new Human('yamada', 170, 60, '男', 30);
yamada.walk();

実行結果↓

課題


理解度チェック
JavaScript→1-7というフォルダの中に作成してください。
出力の結果はconsole.logで表示してください。

問1:以下の要件を満たすように「たい焼きクラス」を作成してください。

【要件】
・クラス名:Taiyaki
・インスタンス化する度に「あんこ」「クリーム」「チーズ」等と中身を変えられるように実装してください。
(コンストラクタで渡ってきた引数をセットする)
・「中身は〇〇です」と中身を出力する関数を作成してください。

カテゴリー

アーカイブ

Close Bitnami banner
Bitnami