この章のキーワード
- オブジェクト
- クラス
- 属性
- メソッド
- インスタンス化する
- コンストラクタ
この章のキーワード
ここでは、「 オブジェクト指向プログラミング 」について学びます。標題にある「 クラス 」とは、オブジェクト指向プログラミングに必要な部品の一つです。
まず、「オブジェクト指向プログラミング」とはなんでしょうか。オブジェクト指向プログラミングとは、「 オブジェクト という 概念 に基づいた プログラミング手法 」です。
では、「 オブジェクト 」とは、なんでしょうか。直訳すると、オブジェクトは「 物体 」「 モノ 」「 塊 」となります。ですから、身の回りにある もの すべてがオブジェクトです。「人間」「家」「車」「プレーヤー」などをオブジェクトとして考えることができます。前述したように、オブジェクトは具体的な物というよりは 概念 です。考え方です。プログラミングにおいては、オブジェクトというモノは「 内部状態(データ) 」と「 振る舞い 」を持っているとしています。
つまり「オブジェクト指向プログラミング」とは、「内部状態」と「振る舞い」を持っている塊(オブジェクト)を使ってプログラムをしていこう、というやりかたです。
ここでオブジェクトの例として、人間を例にして考えてみましょう。人間というオブジェクトは、次のような 状態 を持ちます。
- 名前- 性別- 年齢 など
また、次のような 振る舞い を持っています。
- 挨拶をする- 名前を言う など
オブジェクト指向プログラミングでは、オブジェクトが持っている状態(データ)を「 属性 」と言います。また、オブジェクトが実行できる振る舞いを「 メソッド 」と言います。
クラス は、オブジェクトを作成するための 設計図 のことです。この設計図で、「属性」と「メソッド」を定義しています。先ほどの人間というオブジェクトをクラス図で書いてみましょう。クラスという設計図では、これらのことを定義しています。(なお、プログラミングの説明のため、実際の人間の持つ属性・メソッドのごく一部だけを取り上げています。)
人間のクラス図
クラス名 | Ningen |
属性 | name gender age |
メソッド | sayHello() sayName() |
ここでは、クラス(設計図)の詳細な中身は後で触れることして、設計図であるクラスからオブジェクトを作成するところから見ていきましょう。(家や自動車で言えば、設計図を基に実際のモノを施工したり製造したりすることにあたります) 新たにオブジェクトを作成することを「 インスタンス化する 」(英:instance)と言います。なお、作成された各オブジェクトは「 インスタンス 」(実体、実例)と呼ばれます。インスタンス化するには、プログラム中で下記のように記述します
tentokun = Ningen()
これで、Ningenクラスのオブジェクトが新たに作成され、それを変数tentokunに代入しています。 インスタンス化する際には、Ningenクラス(設計図)の中で定義されている特殊な初期化メソッドを使ってオブジェクトを初期化します。この初期化メソッドのことを「 コンストラクタ 」と呼びます。つまり、コンストラクタは新たに作成されるオブジェクトの属性値を初期設定するメソッドなのです。
実際のプログラムコードを見てみましょう。 クラスの書き方、オブジェクトの作成、および使い方は以下のようになります。
class Ningen: #コンストラクタ def __init__(self): self.name = "テント" self.gender = "男" self.age = 10
#その他のメソッド def sayHello(self): print("Hello!")
def sayName(self): print("私の名前は", self.name, "です")
tentokun = Ningen() # インスタンス化print(tentokun.name)tentokun.sayHello()tentokun.sayName()print()
print(tentokun.age)tentokun.age = 20print(tentokun.age)
class Ningen:のブロックがNingenクラスの定義(設計図)になります。
tentokun = Ningen() 以下が実行プログラムの部分です。
実行結果
テントHello!私の名前は テント です
1020
最初に、「class」というキーワードに続けて クラス名 を書きます。慣例として、 クラス名の最初は大文字 にします。
このクラスの持っている 属性 のデフォルト(初期値)は コンストラクタ の部分に書かれており、
name = "テント" gender = "男" age = 10
となっています。
なお、クラスの持っている メソッド は def で関数定義されます。オブジェクトの作成時に初期化をするコンストラクタメソッドも、その他のメソッドも、同じように def で定義されます。
コンストラクタメソッド は特別に、 __init__ という名前です。__init__の前後にはそれぞれ、2つの”_(アンダーバー/アンダースコア)“があります。見慣れない形ですが、最初のうちは、コンストラクタはこういう風に書くんだ、と覚えてください。
メソッドの定義の中で self という変数が使われていますが、直訳すると「自分自身」です。つまり、このクラス(設計図)で作成されるオブジェクト自信を意味します。これは、 self.属性名 という形で、この作成されるオブジェクトの属性値の参照や設定に使われます。
実行プログラムの部分を見てみましょう。 まず、オブジェクトの持っている 属性 の値を知ったり変更したりするには、 変数の後にドット (.)を付け、その後に 属性名 を記述します。
書式 | 変数.属性名 |
例 | 属性値を表示する print(tentokun.name) 属性値を変更する tentokun.age = 20 |
また、オブジェクトの持っている メソッド を実行させるには、 変数の後にドット (.)を付け、その後に メソッド名を()を付けて 記述します。
書式 | 変数.メソッド名() |
例 | メソッドを実行する tentokun.sayHello() |
属性 を追加してみましょう。例えば、学校、趣味、得意科目、誕生日など。また、それらを表示する メソッド も追加してみましょう。
上記のクラスNingenでは、名前が「テント」、性別が男、年齢が10歳の人間オブジェクトしか作成されません。違う属性(名前や性別、年齢)の人間オブジェクトを作成するにはどうすればよいでしょうか。
例えば、このNingenクラス(設計図)でインスタンス化した後にひとつひとつ属性を変更していくのでもできますが、インスタンス化するときに引数を指定するようにして、最初から違う属性を持つオブジェクトを作成するようにすることもできます。
そのように改良したプログラムは以下のようになります。
class Ningen2: #コンストラクタ def __init__(self, n, g, a): #引数を受け取れるように改良 self.name = n self.gender = g self.age = a
#その他のメソッド def sayHello(self): print("Hello!")
def sayName(self): print("私の名前は", self.name, "です")
tenkochan = Ningen2("テンコ","女",12) #インスタンス化時に引数を指定print(tenkochan.name)tenkochan.sayHello()tenkochan.sayName()print()
tenzoukun = Ningen2("テンゾウ","男",6) #インスタンス化時に引数を指定tenzoukun.sayName()
実行結果
テンコHello!私の名前は テンコ です
私の名前は テンゾウ です
独自の クラス を作ってみましょう。例えば「車」という オブジェクト の クラス なら、 属性 は「メーカー」「高さ」「横幅」「速さ」「現在位置」など、 メソッド は「前進」「後退」などが考えられます。その他「料理」「プレーヤー」「モンスター」「野球チーム」などのオブジェクトもおもしろいでしょう。
いろいろな関数を使ってオブジェクトの情報を知ることができます。前述のNingenクラスのオブジェクトtentokunについて調べてみましょう。
例
class Ningen: #コンストラクタ def __init__(self): self.name = "テント" self.gender = "男" self.age = 10
#メソッド def sayHello(self): print("Hello!")
def sayName(self): print("私の名前は", self.name, "です")
import pprinttentokun = Ningen() # インスタンス化print(type(tentokun))print(dir(tentokun))pprint.pprint(dir(tentokun))print(vars(tentokun))
書式
type(オブジェクト)
例
print(type(tentokun))
##<class '__main__.Ningen'>
書式
dir(オブジェクト)
例
print(dir(tentokun))
##['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'gender', 'name', 'sayHello', 'sayName']
(参考)見やすく出力する:pprint()
属性やメソッドを1行ずつ表示します。これにはpprintライブラリをインポートする必要があります。
書式
import pprintpprint.pprint(dir(オブジェクト))
例
import pprintpprint.pprint(dir(tentokun))
##['__class__',## '__delattr__',## '__dict__',## (途中省略)## 'age',## 'gender',## 'name',## 'sayHello',## 'sayName']
書式
vars(オブジェクト)
例
print(vars(tentokun))
##{'name': 'テント', 'gender': '男', 'age': 10}