オブジェクト指向プログラミングとは
「モノ」を組み立てるように表現して,コンピュータに動作をさせる
例を交えて,各用語を説明する.
オブジェクト,インスタンス:
各々の家(現実に存在する)
伊藤君の家,佐藤君の家,...
クラス:それぞれの家の設計図(実在しない)
家の設計図
クラスから実態を作成されたもの.
→オブジェクト-object-(インスタンス-instance-)
クラスから実態を作成すること.
→インスタンス化-instantiation-
実際にクラスを作成していこう.
家は,各々同じ構造で,違うのは表札だけであるとする.
すると,次のように期待できる.
クラス | House |
---|---|
属性 | name_plate |
これを,Pythonで実装すると次のようになる.
class House:
def __init__(self, name):
self.name_plate = name
ここで,いろいろと期待していなかった文字列が登場している.
これらは,次のようである.
def
:
関数の宣言時に必要な接頭語
__init__
:
関数名は,任意の名前を付けることが可能だが,__init__
とすると特別な意味を持つ
それは,インスタンス化する際に,自動的にこの関数が呼ばれるということである.
self
:
クラスを呼び出して,新しいインスタンスが作成されたときのインスタンス名が何なのか,クラスの定義時(プログラム作成時)にはわからない.
そのため,実際にユーザがクラスを呼び出したときに用いた名前を得るために'self'を用いている.
慣例的に"self"とすると,自分自身のインスタンス名を表すことになっているが,別の文字列でもよい.
name
:
実際にname_plateに代入したい名前を疑似的に"name"としている.
具体例:
satoHouse = class("佐藤")
##メソッド
先ほどは,クラスからインスタンスを作成したときに自動的に行われる処理を定義しただけであるので,具体的にメソッドは定義していなかった.
そこで,クラス Houseにメソッド helloを追加して,次のようにしたい.
クラス | House |
---|---|
属性 | name_plate |
メソッド | hello |
Pythonで書くと,次のようになる.
class House:
def __init__(self, name):
self.name_plate = name
def hello():
print("{}の家です.".format(self.name_plate))
ここで,format関数をさりげなく使っている.
###format関数
"任意の文字列{}任意の文字列".format( {}の部分に挿入したい文字列 )
このように書ける.
このように,インデックス指定もできる.
"任意の文字列{0}任意の文字列{1},...".format({0}の部分に挿入したい文字列, {1}の部分に挿入したい文字列)
継承-inheritance-
クラスを定義した後で,
「あのメソッド便利だったなー.今定義したクラスでも使いたいなー.再定義面倒だなー.」
という場合に継承が便利である.
次のようなクラスを用意し,
クラス名 | Link |
---|---|
属性 | a |
b |
新しく作った次のクラス,
クラス名 | Chain |
---|---|
メソッド | sum |
に継承させる. | |
つまり,次のような構造にする. |
クラス名 | Chain |
---|---|
属性 | a |
b | |
メソッド | sum |
Pythonでは,次のように実装できる.
class Link:
def __init__(self):
self.a = 1
self.b = 2
いざ,継承
class Chain(Link):
def sum(self):
return self.a + self.b
classの定義時に,次のようにすると良い.
class クラス名(継承したいクラス名):
これでうまくいくはずである.
次に,継承した子クラスのほうを今編集しているはずなので,
子クラスのほうで,新しく属性を定義してみたいと思う.
つまり,こうしたい
クラス名 | Chain |
---|---|
属性 | a(Link由来) |
b(Link由来) | |
c(Chain内部で定義) | |
メソッド | sum |
こうするとよさそう.
class Chain(Link):
def __init__(self):
self.c = 5
def sum(self):
return self.a + self.b + self.c
C = Chain()
C.sum()
しかし,これを実行すると,次のようなエラーが出る.
AttributeError: 'Chain' object has no attribute 'a'
理由は,親クラスでも,**__init__が定義されており,
子クラスの__init__**が優先的に呼び出され,属性a,bは定義されていないことになるからである.
これは,super関数を使うことで回避できる.
このようにする.
class Chain(Link):
def __init__(self):
super().__init__()
self.c = 5
def sum(self):
return self.a + self.b + self.c
C = Chain()
C.sum()
super()は,親クラスを参照する関数である.
.(ドット)以下に,呼び出したい関数を書く
こうすることで,親クラスの関数を呼び出している.
おわりに
拙い文章で申し訳ないです.
役に立ってくれたら幸いです.
引用
- Python 入門 — ディープラーニング入門:Chainer チュートリアル
https://tutorials.chainer.org/ja/02_Basics_of_Python.html#%E3%82%AF%E3%83%A9%E3%82%B9