クラスとインスタンス
上から順に処理を実行していくプログラムのことを「手続き型」プログラミングといいます。これに対して、オブジェクト指向プログラミングではオブジェクトを生成し、オブジェクトを組み合わせてプログラムを構築します。
このオブジェクトの生成に必要なものがクラスです。クラスとは、オブジェクトの特性を記述したもので、簡単に言うとオブジェクトの仕様が書かれた設計図です。そして、クラスから生成されたオブジェクトをインスタンスといいます。
クッキーの型をクラス、クッキーをインスタンスに例えると、クッキー型(クラス)を使うことによって大量の同じ形のクッキー(インスタンス)を作ることができます。また、材料(データ)を変えることで種類の異なるクッキー(インスタンス)ができます。
クラスはあくまで型であって中身がなく、インスタンスの特性を記したものです。具体的なデータを与えることで実体としてインスタンスが生成されます。
また、上図の例ではクッキー型という実体がありますが、様々な種類のクッキーの総称として、まとめて「クッキー」と呼ぶことができます。総称としてのクッキーに実体はなく、クッキーの特徴だけを集めたものです。これを、オブジェクト指向では抽象化といいます。クラスもまた実体がなく特徴だけを集めた抽象であり、具体化したものがインスタンスと捉えることができます。
クッキーを表すクラスを設計してみよう
クラスを設計することをクラス定義といいます。そして、クラス定義にはclass文を使用します。
class クラス名:
クラスの内容
クラス定義の書式は、関数を定義する書式に似ています。クラスの内容はインデントしたブロックに記述します。また、クラス名は慣習的に大文字で始めます。大文字で始めることで関数とクラスの判別をしやすくするためです。
では実際にクッキーのクラスを定義してみましょう。
class Cookie:
pass
これでクッキーのクラスが定義できました。クラスの内容は、ここでは何も実行しないpass
を記述しています。
クッキーのクラスからインスタンスを生成する
クラス定義によってクッキー型はできましたが、まだ実体がありません。ここからクッキー型(クラス)を元に、クッキー(インスタンス)を生成する必要があります。
クラスからインスタンスを生成するには、以下の書式で記述します。
インスタンス名 = クラス名()
インスタンスの生成も、関数を呼び出すときと同じように、クラス名に括弧()を付けて変数に代入します。
では先ほどのCookie
クラスからクッキー(インスタンス)を作りましょう。
class Cookie:
pass
cookie1 = Cookie()
Cookie
クラスからcookie1
というインスタンスが生成できました。
クラスの内容にはpass
しか記述していないため、cookie1
インスタンスには何のデータもありません。これだけでは味気ないので、次はクッキーにデータを与えましょう。
クラス変数とインスタンス変数
データ(属性)とメソッド(操作)を一つのまとまりにしたものがオブジェクトです。クラスにデータを設定することで、共通のデータを持つインスタンスが生成されます。このような共通データをクラス変数といいます。一方、それぞれのインスタンスが持つデータをインスタンス変数といいます。
クラスをクッキー型とするなら、クラス変数が共通のクッキーレシピ、インスタンス変数は実際のクッキー生地やトッピングに例えられます。
※ クラス変数やインスタンス変数をクラス(インスタンス)のアトリビュートや属性ともいいますが、ここではクラス(インスタンス)変数で統一します。
以下の書式でクラス変数を設定します。
class クラス名:
クラス変数名 = 値
また、クラス変数、インスタンス変数、それぞれの値を呼び出すには以下の書式で記述します。
クラス名.クラス変数名
インスタンス名.インスタンス変数名
それでは、先ほどのクッキー型にレシピを与え、レシピ通りのクッキーができたか確認してみましょう。
ここでは、Cookie
クラスにクラス変数taste
とname
のデータを設定し、クラス変数を呼び出して表示。その次に、cookie1
インスタンスを生成し、cookie1
のインスタンス変数を呼び出して表示します。
class Cookie:
# クラス変数を設定する
taste = "プレーン"
name = "クッキー"
# クラス変数を呼び出し表示する
print(Cookie.taste, Cookie.name)
# インスタンスを生成する
cookie1 = Cookie()
# インスタンス変数を呼び出し表示する
print(cookie1.taste, cookie1.name)
実行してみましょう。
プレーン クッキー
プレーン クッキー
クッキー型に与えたレシピからプレーン味のクッキーができました。
クッキーインスタンスは、クラスで設定された初期データ(クラス変数)が与えられ、プレーン味のクッキーとして作成されます。結果として表示されている内容はどちらもプレーンクッキー
ですが、このとき呼び出している変数は、1行目がクラス変数(レシピ)、2行目は**インスタンス変数(クッキー自体の情報)**という違いがあります。
インスタンス変数を追加・更新する
では、クッキーインスタンスのtaste
データを更新して、違う種類のクッキーも作成しましょう。さらに、インスタンス変数を追加して、クッキーの値段をつけます。インスタンス変数を追加・更新するには、値を呼び出すときと同じ書式を使います。
インスタンス名.インスタンス変数名 = 値
それでは、先ほどのクッキーインスタンスのデータを追加・更新し、呼び出してみましょう。
class Cookie:
# クラス変数を設定する
taste = "プレーン"
name = "クッキー"
# インスタンスを生成する
cookie1 = Cookie()
cookie2 = Cookie()
# インスタンス変数の値を更新する
cookie2.taste = "チョコ"
# インスタンス変数を追加する
cookie1.price = 100
cookie2.price = 200
# インスタンス変数を呼び出し表示する
print(cookie1.taste, cookie1.name, cookie1.price, "円")
print(cookie2.taste, cookie2.name, cookie2.price, "円")
実行してみましょう。
プレーン クッキー 100円
チョコ クッキー 200円
cookie2
のtaste
データを更新して、プレーン味からチョコ味に変更ができました。また、新たに値段のデータを追加することができました。
このように、インスタンス変数はクラス定義の外から追加・更新ができます。クラス定義に存在しないデータを、インスタンスが独自に持つことができる点は、他のプログラミング言語にはあまりない特徴です。
クラス変数を追加・更新する
実は、インスタンス変数と同様に、クラス変数もクラス定義の外から追加・更新することが可能です。
クラス名.クラス変数名 = 値
それでは、先ほどのクッキークラスのデータを更新し、呼び出してみましょう。
class Cookie:
# クラス変数を設定する
taste = "プレーン"
name = "クッキー"
# インスタンスを生成する
cookie1 = Cookie()
cookie2 = Cookie()
# インスタンス変数の値を更新する
cookie2.taste = "チョコ"
# クラス変数の値を更新する
Cookie.name = "せんべい"
# インスタンス変数を呼び出し表示する
print(cookie1.taste, cookie1.name)
print(cookie2.taste, cookie2.name)
実行してみましょう。
プレーン せんべい
チョコ せんべい
クラス変数のname
データを更新して、クッキーがせんべいになりました。
ただし、このようにクラス定義の外部でクラス変数を変更されるプログラムは推奨されません。
オブジェクト指向において、クラスはオブジェクトの設計図であり、型でもあります。クッキー型が途中でせんべい型に代わることは、設計者が望まない変更と言えるでしょう。
また、同様にチョコ味への変更、つまりインスタンス変数の値の更新も推奨されません。あらかじめ与えられたクラス変数を更新することで、意図せずクラス変数を隠蔽してしまうためです。クラス変数はすべてのインスタンスで共通の変数、インスタンス変数はそのインスタンス固有の変数であるべきなのです。
初学者のためのPython講座 オブジェクト指向編1 オブジェクト指向とは
初学者のためのPython講座 オブジェクト指向編2 クラスとインスタンス
初学者のためのPython講座 オブジェクト指向編3 メソッド
初学者のためのPython講座 オブジェクト指向編4 初期化メソッド
随時追加予定