オブジェクト指向プログラミングと聞くと少し難しいイメージがありますが、簡単に言うと自分のことは自分でできるようにオブジェクトに機能を持たせるということです。

このオブジェクト指向プログラミングは他のプログラミング言語(Java、Python、C#、C++、Ruby、PHPなど)でも使用されるため、ここで理解しておけばで他の言語でも活かすことができます。

オブジェクト指向の考え方

以前、JavaScriptの基礎でオブジェクトについて学習しました。(まだの方はオブジェクトと関数(変数スコープの説明あり)を御覧ください)

例えば、人である「らくま たろう」さんをオブジェクトにしてみると以下のようになります。


{
    firstName: 'Taro',
    lastName: 'Rakuma'
}
                

では、このデータのフルネームをコンソールに表示する処理を書く場合、どう書きますか?


const user = {
    firstName: 'Taro',
    lastName: 'Rakuma'
}

console.log(user.firstName + ' ' + user.lastName);
                

こう書けば簡単に実装できますね。

ただ、オブジェクト指向の場合はこうではありません。冒頭でも書いている通り、オブジェクト指向は「自分のことは自分でできるように」設計します。

上記処理をオブジェクト指向で書いたら以下のようになります。


const user = {
    firstName: 'Taro',
    lastName: 'Rakuma',
    fullname: function() {
        console.log(this.firstName + ' ' + this.lastName);
    }
}

user.fullname();
                

フルネームをコンソールに表示するという処理そのものをオブジェクトに持たせました。

このようにオブジェクト自身の処理はオブジェクトが持つことで処理の追記や呼び出し、メンテナンス、テストが簡単になるといった利点があります。

クラスの使い方

Class instantiation(クラスのインスタンス化)

先程の例ではJavaScriptの値であるオブジェクト型に関数を設定しましたが、通常は class (クラス)を定義して使用します。

なぜ class を使用する必要があるのか考えてみましょう。

例えば、先程の例で使用した「人」のデータが以下のように配列で来た場合どうしますか?


[
    {
        firstName: 'Taro',
        lastName: 'Rakuma'
    },
    {
        firstName: 'Hanako',
        lastName: 'Rakuma'
    }
]
                

それぞれのオブジェクトに fullname 関数を設定するのはちょっと手間が掛かりますね。

この様な場合に class という設計図を予め作成しておくことができます。

クラスの作成

class を使用する場合は、予め定義しておく必要があります。

JavaScriptのクラス構文

先程の例を元に class を定義してみます。


                    
class User {
    constructor(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    fullname() {
        console.log(this.firstName + ' ' + this.lastName);
    }
}
                

これで class という設計図を定義することができました。

インスタンス化

この class を使用する場合は、この設計図にデータを与えてオブジェクト(インスタンス)を生成する必要があります。

このことを インスタンス化 と言います。


// インスタンス化
const user = new User('Taro', 'Rakuma');
// メソッド呼び出し
user.fullname();
                

クラス名について

class のあとは クラス名 を指定します。このクラス名は他のクラス名と同じ名前を付けることはできません。

また頭文字を大文字にしたキャメルケースで命名します。

例: AnimalTimeZone

コンストラクタについて

constructor(コンストラクタ)は class のインスタンスを生成する時に一度だけ実行されます。

一番最初に実行されるので初期化処理を記述します。

また constructorclass一つしか定義できません

メソッドについて

class 内の関数のことを method(メソッド)と呼びます。

fullname() のようなメソッドは インスタンスからしか呼び出すことができませんが、

static sayHello() のように頭に static を付けると静的メソッドとなりインスタンス化する前のみ呼び出すことが出来るメソッドを定義できます。



class User {
    constructor() {
        // 初期化...
    }

    static sayHello() {
        console.log('こんにちは');
    }
}

User.sayHello(); // インスタンス化前のみ呼び出し可能
                

プロパティについて

constructor 内で初期化している this.firstName などはインスタンスのプロパティと呼ばれ、このインスタンスが持つ変数となります。

class 内では this.プロパティ名 で参照することができます。

インスタンスからは、インスタンス名.プロパティ名 で参照できます。

また、constructor だけではなく、以下のように予めプロパティを設定することができます。


class User {
    firstName = '';  // プロパティ
    lastName = '';   // プロパティ
    constructor(firstName, lastName) {
        // this. を先頭につけて参照
        this.firstName = firstName;
        this.lastName = lastName;
    }
}
// インスタンス化
const user = new User('Taro', 'Rakuma');
// インスタンス名.プロパティ名 で参照
console.log(user.firstName); // Taro
                

継承について

クラス特徴を引き継いだ派生した新しい class を定義することを継承と言います。

この基となるクラスをスーパークラス と呼び、派生したクラスを サブクラス と呼びます。

継承には extends を使用し、一つの class からしか継承することはできません


class AppUser extends User {
    constructor(userData) {
        super(userData.firstName, userData.lastName);
        this.id = userData.id;
        this.email = userData.email;
        this.avatar = userData.avatar;
    }
}

let user = new AppUser(userDaya);
user.fullname();
                

スーパークラスを呼び出すsuper

スーパークラスとサブクラスには親子関係ができます。

super を使用して 子から親のメソッドを呼び出すことができます。

例:  super.メソッド()

上の例では コンストラクタ で super() とすることで、親の コンストラクタ を実行しています。

継承を行っている場合、この呼び出しは、コンストラクタで一番最初に行わなければなりません

オーバーライド

サブクラスにはスーパークラスと同名のメソッドを作成することができます。作成後に、サブクラスでこの同名のメソッドを呼び出した場合は、スーパークラスではなくサブクラスのメソッドが使用されます

これをオーバーライドといいます。

課題

プロパティに name(文字列) と weight (数値)があり、コンストラクタで初期化するクラス Animal を作成してください。

Animal に プロパティ weight0.5ずつ増加させる eat メソッドを作成してください。

また増加後の weight をコンソールに表示するように eat メソッド内に記述してください。

クラス Animal{name: 'ココ', weight: 500} のデータでインスタンス化してください。

課題3でインスタンス化したオブジェクトで、メソッド eat を実行し、weight0.5 増えたことを確認してください。

クラスAnimal を継承した クラスDog を作成してください。

この時 eat メソッドをオーバーライドして、増加させる weight1 に変更してください。

クラスDog を次のデータでインスタンス化してください。

{name: 'ポチ', weight: 2000}

インスタンス化したクラスDog のオブジェクトの eat メソッドを実行して、weight2001 となることを確認してください。