オブジェクト・クラス・インスタンス、区別OK?

この記事では、変数と関数しかわからなくても、読めば、オブジェクト、クラス、インスタンス、プロパティ、メソッド、コンストラクタについてのイメージが掴めるようになります。

まずは、オブジェクト・クラス・インスタンス・メソッド・プロパティ・コンストラクタについて、まとめた画像を見てみましょう!※あくまで、個人のイメージ画像です。

オブジェクトとは?

プログラミングにおいて「オブジェクト」という言葉は、2つの文脈で使われます。私は、広い意味でのオブジェクト狭い意味でのオブジェクトと呼ぶことにしています。

広い意味でのオブジェクト

広い意味では、名前と値のペアを持つデータ構造全般をオブジェクトと呼ぶことができます。
例として、下記のJavaScriptコードのpersonは、名前と値のペアを持っているので、オブジェクトと呼ぶことができます。

const person = {
  name: "オザキカズヒロ",
  age: 35,
  job: "教師"
};
console.log(person.name);  // オザキカズヒロ

この名前と値のペアを持つデータ構造全般広い意味でのオブジェクトと押さえましょう!
まとめ画像の1番外枠の部分ですね。

クラスやインスタンスも広い意味でのオブジェクトと呼べる

「クラス」というのは、複製目的で作られた広い意味でのオブジェクトと呼ぶことができます。つまり、「コピー用に作った名前と値のペアをもつデータ構造全般」です。よく設計図に例えられます。
これに対して、「インスタンス」は、このクラスから複製して作った広い意味でのオブジェクトと呼ぶことができます。つまり、コピーして作った名前と値のペアをもつデータ構造全般」と言うことができますよね。

狭い意味でのオブジェクト

複製目的で作れられたデータ構造から、複製してデータ構造を作るという操作は、プログラミングの世界ではよく行われます。よって、この部分にだけ注目したときに、あたかも、設計図から物(実体)が作り出されているように見ることができますよね?このような、設計図から物(実体)を作っているように見えるので、この設計図からでき上がったもののことをオブジェクト(インスタンス)って呼ぼう〜となったわけです。これが、私の中では、狭い意味でのオブジェクトです。

プロパティとメソッド

クラス内に記述した変数プロパティと呼び、クラス内に記述した関数メソッドと呼びます。
ただそれだけで、それ以上でもそれ以下でもありません。いたってシンプルです。

クラスの基本的な書き方(PHP)

PHPでは、以下のようにクラスを定義します。

class クラス名 {
    アクセス修飾子 $プロパティ名;

    アクセス修飾子 function メソッド名($引数) {
        // 処理を記述
    }
}

アクセス修飾子とは?

アクセス修飾子とは、どこからプロパティやメソッドにアクセスできるかを制御するものです。
主な種類は次の3つです:

  • public: インスタンスを作れば、どこからでもアクセスできる
  • private: クラスの内部からしかアクセスできない
  • protected: クラス内部およびその子クラスからアクセス可能

デフォルトでアクセス修飾子を省略した場合はpublicとして扱われます。適切に指定することで、意図しないアクセスを防ぐことができます。このあたりの解説は、別の記事で詳しく書きますので、今はそんなものがあるのか〜程度の認識で大丈夫です。

クラスとインスタンスの使い方

クラスは設計図、インスタンスは設計図から生成される具体的なオブジェクトでしたよね。
インスタンス化とは、クラスからオブジェクトを生成することを指します。

// Carクラスの定義
class Human {
    public function run() {
        echo '走ります';
    }
}

// インスタンスを作成
$oz = new Human();  // インスタンス化
$oz->run();      // メソッド呼び出し -> "走ります" と表示

ここで、$ozがHumanクラスから生成されたインスタンスです。
インスタンスのメソッドはアロー演算子 (->) を使って使うことができます。

コンストラクタ

なあ、プロ太先生!オブジェクト、クラス、インスタンス、プロパティ、メソッドってのは分かってんけど、コンストラクタってのもあるって聞いたんやけど、コンストラクタってなんなん?

じゃあ、まず基本から説明しましょう。
コンストラクタは、クラスを使ってオブジェクト(インスタンス)を作ったときに自動的に実行される関数だよ。たとえば、オブジェクトを作るときに毎回何かの初期設定が必要な場合、コンストラクタでその処理をまとめておくと便利なんです。

う〜ん、、、なんかピンとけ〜へんねんな〜。

では、例のコードを見せましょう。例えば、Studentというクラスを作って、オブジェクト(インスタンス)を生成したときに名前を設定したいとしましょう!

<?php
class Student {
    public $name;

    // コンストラクタの定義
    public function __construct($name) {
        $this->name = $name;
        echo "学生の名前は {$this->name} です。\n";
    }
}

// オブジェクトの生成と同時にコンストラクタが呼ばれる
$ozkun = new Student("OZくん");
?>

おお!!なるほど!オブジェクト作った瞬間に名前がセットされるんやな!
new Student(引数)の引数の部分に名前を入力してオブジェクト(インスタンス)を作れば、自動で名前を設定してくれんやな!便利や〜!!ちなみにコンストラクタを使わん場合は、どんな感じになるの?

なるほど!いいですね。では使わないバージョンだとどうなるか、比較しておきましょう!

<?php
class Student {
    public $name;

    // 名前を手動で設定する関数
    public function setName($name) {
        $this->name = $name;
    }

    public function greet() {
        echo "こんにちは、{$this->name} です!\n";
    }
}

// オブジェクトを生成
$ozkun = new Student();

// 名前を後から手動でセットする
$ozkun->setName("OZくん");

?>

どうですか?2つのコードの違いは見えましたか?

はい!コンストラクタを使わんかったらまずオブジェクトを作ってから setName() を実行せなあかんってことやな。これやと忘れる可能性もあるし、コードも増えてまう。

その通りです!コンストラクタを使うとオブジェクトを生成するだけで初期化が完了するので、毎回 setName() を呼ぶ手間が省けます。しかも、初期化を忘れるリスクも減りますね。しっかりと使いこなせるようにしておきましょうね!

クラス(設計図)の書き方(JavaScriptとPHP比較)

ここからは、JavaScriptとPHPのクラス(設計図)の書き方の違いを見ておきましょう。
まずはJavaScriptのコードからです。ここではES6の書き方を使います。

class Student {
  constructor(name, grade, subject) {
    this.name = name;
    this.grade = grade;
    this.subject = subject;
  }

  introduce() {
    return `僕は${this.name}で${this.grade}年生です。好きな教科は${this.subject}です。`;
  }
}

const student = new Student('たろう', 2, '数学');
console.log(student.introduce());

次に、PHPでの書き方です。

<?php
class Student {
    public $name;
    public $grade;
    public $subject;
    
    public function __construct($name, $grade, $subject) {
        $this->name = $name;
        $this->grade = $grade;
        $this->subject = $subject;
    }
    
    public function introduce() {
        return "僕は{$this->name}で{$this->grade}年生です。好きな教科は{$this->subject}です。";
    }
}

$student = new Student('たろう', 2, '数学');
echo $student->introduce();
?>

へー!JavaScriptもPHPも似てる感じがしますね!

そうですね。ES6以降のJavaScriptは、クラスを使った書き方ができるようになって、PHPとより似た構造になりました。

重要なポイントは、

  1. クラス(設計図)を定義する
  2. コンストラクタ(初期化メソッド)を使ってオブジェクトの初期状態を設定する
  3. メソッドを定義してオブジェクトの振る舞いを決める
  4. newキーワードを使ってインスタンス(設計図から作った新しいオブジェクト)を作る

という流れは同じということです。
これがオブジェクト指向プログラミングの基本的な考え方になります。

補足:JavaScriptのES5では、クラス構文がない!

JavaScriptにおいて、旧ES5バージョンでは、クラスというものが存在しませんでした。ES5での書き方も、念のため、見ておきましょう。

let Animal = function(species, sound, habitat) {
  this.species = species;
  this.sound = sound;
  this.habitat = habitat;
  this.makeSound = function() {
    console.log(this.species + 'は' + this.sound + 'と鳴いて、' + this.habitat + 'に住んでいます。');
  }
}

let cat = new Animal('ネコ', 'ニャー', '家');
let lion = new Animal('ライオン', 'ガオー', 'サバンナ');

cat.makeSound();
lion.makeSound();

旧版ES5では、クラスがないため、上記の例で言うと、Animalという関数がコンストラクタの役割を果たしています。
そして、newキーワードを使うことで、この関数を基にして新しいオブジェクトを作成しているんですよ。

へぇ〜、このES5での書き方も覚えておかないといけませんか?

知っておくくらいで大丈夫ですよ。既存のプロジェクトやコードにはES5で書かれたコードは、当然まだ存在します。なので、ES6を中心に学習しつつ、必要に応じてES5の知識も身につけることが望ましいです。

まとめ

クラスを使うと、似たようなものをたくさん作るのが簡単になり、プログラムが整理しやすくなります。最初は難しく感じるかもしれませんが、少しずつ慣れていくことが大切です。

自分だけのクラスを作れるようになると、プログラミングの可能性がぐんと広がります!

これからもプログラミングを楽しみながら学んでいきましょう!