オブジェクト指向基礎
そもそも「オブジェクト指向」って何?
プログラミングには種類があり、代表的なものは以下のとおりです。
- 命令型プログラミング
- 関数型プログラミング
- オブジェクト指向プログラミング
- 宣言型プログラミング
例えば、AI開発で用いられるPythonは複数のパラダイムをサポートしますが、特にオブジェクト指向の考え方を理解しておくと良いでしょう。
オブジェクト指向は、プログラムを「モノ(オブジェクト)」ごとにまとめて考える方法です。ゲームなら「主人公」「敵キャラクター」「アイテム」など、現実世界のモノに近い形で扱うイメージです。
モノ(オブジェクト)は、プロパティ(属性)とメソッド(動作)を持っています。
ロボットの例:
プロパティ:「名前」や「色」
メソッド:「挨拶する」「計算する」
プログラミングでこれらのオブジェクト指向を使うとき、大事なのが「クラス」という仕組みです。
クラスとは何か?
クラスはオブジェクトの設計図のようなものです。設計図に沿って実際につくられる具体的なモノを「インスタンス」と呼びます。
ロボットの例:
クラス:ロボットの設計図
インスタンス:設計図を元に作られた「赤い自転車」「青い自転車」
class Robot:
# ロボットを作るときの設定(初期化)
def __init__(self, name, color):
# プロパティの設定
self.name = name # 名前
self.color = color # 色
# メソッド1:挨拶する
def greet(self):
return f"こんにちは!私は{self.color}色の{self.name}です!"
# メソッド2:計算する
def calculate(self, num1, num2):
sum_result = num1 + num2
return f"{num1} + {num2} = {sum_result}です!"
# インスタンス(実際のロボット)を2体作ってみましょう
robo1 = Robot("ピコ", "赤")
robo2 = Robot("タマ", "青")
# それぞれのロボットに挨拶させてみる
print(robo1.greet()) # -> "こんにちは!私は赤色のピコです!"
print(robo2.greet()) # -> "こんにちは!私は青色のタマです!"
# それぞれのロボットに計算させてみる
print(robo1.calculate(5, 3)) # -> "5 + 3 = 8です!"
print(robo2.calculate(10, 7)) # -> "10 + 7 = 17です!"
クラスには、「オブジェクトが持つべき特徴量(プロパティ)」と「オブジェクトができること(メソッド)」を定義します。
インスタンスを作るときに、クラスが示す内容(プロパティとメソッド)を引き継ぐ形で利用できるようになります。
クラスの継承
オブジェクト指向には3大要素があります:
- カプセル化:関連する情報と動作をひとまとめにする(キャラクターの名前と体力をセットで管理)
- 継承:既存の機能を受け継いで新しいものを作る(基本キャラクターの機能を受け継いで戦士や魔法使いを作る)
- ポリモーフィズム:同じ名前の動作でも、状況に応じて中身を変えられる(攻撃方法が職業によって変わる)
以下では特に重要なクラスの継承を解説します!
学校の例:
# 基本となる「学校の人」クラス
class SchoolPerson:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
return f"私の名前は{self.name}です。{self.age}歳です。"
def enter_school(self):
return f"{self.name}が学校に入りました"
# 生徒クラス(SchoolPersonを継承)
class Student(SchoolPerson):
def __init__(self, name, age, grade):
# 親クラスの機能を引き継ぎ
super().__init__(name, age)
# 生徒独自の属性を追加
self.grade = grade
def study(self):
return f"{self.name}は勉強中です"
# 親クラスのメソッドを上書き(オーバーライド)
def introduce(self):
return f"私は{self.grade}年生の{self.name}です。{self.age}歳です。"
# 先生クラス(SchoolPersonを継承)
class Teacher(SchoolPerson):
def __init__(self, name, age, subject):
super().__init__(name, age)
# 先生独自の属性を追加
self.subject = subject
def teach(self):
return f"{self.name}先生は{self.subject}を教えています"
# 親クラスのメソッドを上書き(オーバーライド)
def introduce(self):
return f"私は{self.subject}担当の{self.name}です。{self.age}歳です。"
# それぞれのインスタンスを作成
student1 = Student("田中", 15, 2)
teacher1 = Teacher("佐藤", 30, "数学")
# 継承したメソッドを使う
print(student1.enter_school()) # "田中が学校に入りました"
print(teacher1.enter_school()) # "佐藤が学校に入りました"
# 独自のメソッドを使う
print(student1.study()) # "田中は勉強中です"
print(teacher1.teach()) # "佐藤先生は数学を教えています"
# オーバーライドしたメソッドを使う
print(student1.introduce()) # "私は2年生の田中です。15歳です。"
print(teacher1.introduce()) # "私は数学担当の佐藤です。30歳です。"
- 共通の特徴は親クラスに書く
名前、年齢、学校に入る機能など
SchoolPerson
クラスに書いた機能は、生徒も先生も使える! - 独自の特徴は子クラスに書く
生徒なら学年、先生なら担当科目など
Student
クラスにはstudy()
、Teacher
クラスにはteach()
など - 親クラスの機能を変更したいときはオーバーライド
introduce()
メソッドを各クラスで上書き
同じメソッド名でも、それぞれの立場に合った自己紹介ができる - 親クラスの機能を引き継ぐには
super()
を使う
super().__init__(name, age)
で親クラスの初期化を利用
新しい機能を追加しつつ、基本の機能は再利用できる
このように継承を使うと:
- 共通の機能を何度も書く必要がない(コードの再利用)
- 新しい種類の人を追加するのも簡単
- コードが整理されて見やすくなる
__init__
って何?
今更だけど__init__
はPythonのクラスで特別な意味を持つメソッドで、「コンストラクタ」と呼ばれます。
簡単に言うと、「新しいオブジェクトを作るときに自動的に呼ばれる初期設定の関数」です!
例を見てみましょう:
class Dog:
def __init__(self, name, age): # 犬を「作る時」の設定
self.name = name
self.age = age
# 新しい犬を作る
my_dog = Dog("ポチ", 3) # この時に__init__が呼ばれる
__init__を使わないと:
class BadDog:
# 初期設定がない!
pass
bad_dog = BadDog()
# 後から一つずつ設定しないといけない...
bad_dog.name = "ポチ"
bad_dog.age = 3
このように、__init__
を使うと:
- オブジェクトを作る時に必要な情報を設定できる
- 初期設定を忘れる心配がない
- コードがすっきりする
ちなみに、__init__
の前後の__(アンダースコア2つ)は、「Pythonの特別なメソッドだよ」という印です。このような特殊メソッドは他にもいくつかありますが、__init__が最も基本的でよく使われます。
まとめ
- オブジェクト指向は「モノ(オブジェクト)」を中心にプログラムを考える方法。
- クラスはオブジェクトの「設計図」、インスタンスは「具体的なモノ」。
- 継承を使うと:
親クラスに共通の機能を書いてコードを再利用できる。
子クラスで独自の機能を追加したり、動きを変更(オーバーライド)できる。 -
__init__
は初期設定をする特別なメソッド。インスタンスを作るときに自動で呼ばれる。 - オブジェクト指向を使うと、コードが整理されて分かりやすくなり、保守や拡張がしやすくなる。
担当:生駒
Discussion