クラスと変数を使用して OOP モデルをコードに変える

完了

ここでは、じゃんけんゲームの作成を通じて、オブジェクト指向プログラミング (OOP) の価値を評価していきたいと思います。 そのためには、まずゲームを OOP の形式でモデル化する必要があります。

クラス、オブジェクト、状態など、OOP におけるいくつかの基本的な概念の適用が必要になってきます。 このユニットでは、次の事柄について説明します。

  • OOP に関する重要な概念:OOP について話をするには、クラス、オブジェクト、状態など、基本的な概念について理解しておく必要があります。 これらの概念の違いや、相互の関係について理解しておきましょう。
  • OOP における変数:開発者は、変数の取り扱い方法と、変数をオブジェクトに追加する方法について理解しておく必要があります。

オブジェクトとは何ですか?

オブジェクトの概念については、問題の "モデル化" に関する説明の中で、既に何度か触れてきました。 オブジェクトはアクターです。 つまり、システム内で何らかの動作をします。 アクションが実行されると、それ自体、または他のオブジェクト内の状態が変わります。

現実世界でのオブジェクトについて考えてみましょう。 あなたが今駐車場にいるとした場合、何が見えるでしょうか? 通常なら、たくさんの車があって、さまざまな形状、大きさ、色のものが確認できるでしょう。 車を記述するには、車両のメーカー、モデル、色、種類などといったプロパティを使用します。 これらのプロパティに値を割り当てれば、赤のフェラーリや、4WD のジープ、黄色のマスタングなど、どのような車のことを話しているのかがすぐに明らかになります。

Illustration that shows a car object with the properties type and color.

シーンを変えて、ラスベガスのカード デッキを想像してみましょう。 あなたには今、2 つの異なるカード (2 つのオブジェクト) が見えています。 両者には共通のプロパティがあることに気づくはずです。そう、スートですね。 オブジェクトのスートは、クラブ、ハート、ダイヤ、スペードのいずれかになります。 値は、エース、キング、9 などになります。

ヒント

あなたが今いる場所も見回してみましょう。 2 冊の本や 2 つの椅子など、類似した 2 つのオブジェクトを見つけて、それらを最もよく説明できるプロパティを考え、それらを区別できるかどうかを考えてみてください。

クラスとは?

クラスは、特定の種類のオブジェクトのテンプレート定義として機能するデータ型です。

これまでに、OOP システムにはオブジェクトがあって、それらのオブジェクトにはプロパティがあることを学習しました。 オブジェクトと似た概念があります。それがクラスです。

では、クラスはどのようなものなのでしょうか? クラスは、オブジェクトのブループリントです。 クラスが自動車のブループリントだとすれば、オブジェクトは実際に動く車です。 クラスは、開発者がコードで記述するものです。 オブジェクトは、ランタイム環境にコードを実行するように指示したときに取得されるものです。

次の表は、クラスとその結果のオブジェクトの例を示したものです。

クラス Object
車のブループリント ホンダ アコード、ジープ ラングラー
猫のガーフィールド
アイスクリームの説明 イチゴ、チョコレート、またはバニラ

クラスからオブジェクトを作成することは、ブループリントから自動車を作るのと似ています。 オブジェクトを作成する際、プログラムはオペレーティング システムに、オブジェクトを構築するリソース (メモリなど) を要求します。 一方、ブループリントから車を作る場合、工場の担当者は、車を組み立てるために必要な金属、ゴム、ガラスなどのリソースを要求します。

Illustration showing the resource inputs required to assemble a car from a blueprint.

クラスを作成する

Python のクラスは、キーワード class を使用し、次の例のように名前を付けることによって作成されます。

class Car:

クラスからオブジェクトを作成する

クラスからオブジェクトを作成することを、"インスタンス化する" と言います。 これはどういう操作かというと、このテンプレート (クラス) とこれらのスターター値を使用して、十分なメモリを確保し、オブジェクトを作成するようにオペレーティング システムに要求することです。 基本的に、インスタンス化は作成を表す別の言い方です。

オブジェクトをインスタンス化するには、クラスの名前にかっこを追加します。 取得されるものは、次のように、変数に割り当てることができるオブジェクトです。

car = Car()

car は、オブジェクトのインスタンスを保持する変数です。 インスタンス化する (つまりオブジェクトを作成する) 際には、Car() を呼び出します。

OOP の変数と手続き型プログラムの変数

手続き型プログラミングの頃から、皆さんは変数を使って情報を保持し、状態を追跡することに慣れていることでしょう。 これらの変数は、ファイル内の必要な場所で自由に定義できます。 一般的な変数の "初期化" は次のようになります。

pi = 3.14

OOP にも変数はありますが、OOP の変数はそれ自体で定義されるのではなく、オブジェクトに "アタッチ" されます。 オブジェクトの変数は、"属性" と呼ばれます。 オブジェクトに属性がアタッチされている場合、属性は次の 2 つの方法のいずれかで使用されます。

  • オブジェクトについて説明する:たとえば、"説明" の変数の例としては、自動車の色やキリンの模様などが考えられます。
  • 状態を保持する:変数は、オブジェクトの状態を記述する目的にも使用できます。 状態の例としては、エレベーターの階数や、エレベーターが稼働中かどうかなどが考えられます。

クラスに属性を追加する

クラスに追加する必要がある属性 (変数) を把握することは、モデル化作業の一部です。 コードでクラスを作成する方法は学習しましたが、クラスに属性を追加するにはどうすればよいのでしょうか? オブジェクトを作成する (インスタンス化する) 際には、オどのような属性が必要になるかをクラスに伝える必要があります。 OOP では、オブジェクトの作成時に呼び出される特殊な関数があります。"コンストラクター" と呼ばれるものです。

コンストラクター

多くのプログラム言語には、コンストラクターの概念があります。これは、オブジェクトが最初に作成されるときにのみ呼び出される特殊な関数です。 コンストラクターは 1 回だけ呼び出されます。 このメソッドで、オブジェクトに必要な属性を作成します。 また、作成された属性に、任意のスターター値を割り当てます。

Python では、コンストラクターには __init__() という名前が付いています。 また、コンストラクターには特殊なパラメーターとして self を渡す必要があります。 self パラメーターではオブジェクト インスタンスを参照します。 このキーワードに属性を割り当てることは、その属性がオブジェクト インスタンスになるということを意味します。 self に属性を追加しなかった場合、このキーワードは、__init__() の実行が完了した後には存在しなくなる、一時的な変数として扱われます。

注意

また、パラメーター self は、オブジェクト インスタンス上の何かを参照する必要がある、すべてのメソッドに渡す必要があります。 この概念については、次のユニットで説明します。

クラスの属性を追加および初期化する

コンストラクターで属性を設定する例を見てみましょう。

class Elevator:
    def __init__(self, starting_floor):
        self.make = "The elevator company"
        self.floor = starting_floor

# To create the object

elevator = Elevator(1)
print(elevator.make) # "The Elevator company"
print(elevator.floor) # 1

上記の例は、2 つの変数 (makefloor) を持つクラス Elevator を説明したものです。 このコードで重要な点は、 __init__() が暗黙的に呼び出されているという点です。 __init__() メソッドは名前で呼び出すのではなく、オブジェクトの作成時に (次のコード行で) 呼び出されます。

elevator = Elevator(1)

self の不適切な使用

パラメーター self の動作を強調するために、次のコードについて考えてみましょう。このコードでは、コンストラクター __init__() で 2 つの属性 (colormake) が割り当てられています。

class Car:
    def __init__():
        self.color = "Red" # ends up on the object
        make = "Mercedes" # becomes a local variable in the constructor

car = Car()
print(car.color) # "Red"
print(car.make) # would result in an error, `make` does not exist on the object

クラス Carcolormake の両方の属性を作成することが目的である場合は、コードを変更する必要があります。 コンストラクターで、次のように両方の属性が self に割り当てられるようにします。

self.color = "Red" # ends up on the object
self.make = "Mercedes"

ヒント

自主的な演習として、自分がこれから読む本からクラスを作成してみてください。 クラスをどのように記述するかや、そのクラスにどのようなプロパティが必要かについて考えてみましょう。