オブジェクト指向とは
オブジェクト指向とは、プログラミングの手法の一つであり、複雑なプログラムを分かりやすく設計するための方法です。
オブジェクトには状態(属性)と振る舞い(メソッド)があって、それぞれのオブジェクト同士が相互作用をすることでプログラムが実行されます。
例えば、自動車をオブジェクトとして考えると、自動車は「速度」や「車体色」といった状態を持ち、「加速する」「ブレーキをかける」といった振る舞いをします。
このように、オブジェクト指向では、現実世界の事象をオブジェクトとしてモデル化することで、複雑なプログラムを分かりやすく設計することができます。
クラスとインスタンス
クラスは、オブジェクトの設計図のようなものです。
インスタンスは、クラスから実際に作られたオブジェクトのことです。
例えば、自動車をクラスとして定義すると、車種、色、最高速度といった情報を持つクラスがあります。そして、このクラスから作成されたそれぞれの車がインスタンスとなります。
具体的な例として、Pythonのクラスとインスタンスを使ったプログラムを見てください。
以下は、自動車クラスの定義と、そのクラスから作成されたインスタンスの例です。
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def description(self):
return f"{self.year} {self.make} {self.model}"
my_car = Car("Toyota", "Corolla", 2022)
print(my_car.description()) # 2022 Toyota Corolla
上記の例では、Carというクラスを定義し、そのクラスからmy_carというインスタンスを作成しています。my_carインスタンスの属性であるmake、model、yearは、インスタンス作成時に与えられます。また、description()メソッドを定義して、インスタンスの情報を文字列として返すようにしています。
カプセル化
カプセル化は、オブジェクト指向の特徴の一つです。
オブジェクトの内部データや処理を隠蔽し、外部からのアクセスを制限することです。こうすることで、外部からの不正な操作や変更を防ぐことができます。
また、外部からはオブジェクトのインターフェース(公開されているメソッドや属性)のみにアクセスできるため、オブジェクトの内部構造を隠蔽することができます。
例えば、自動車をオブジェクトとして考えると、速度やエンジン回転数といったデータを直接変更できると、車が壊れてしまう可能性があります。
そこで、速度やエンジン回転数などのデータは、カプセル化によって隠蔽され、速度を変更する場合はアクセルを踏むといったオブジェクトの公開メソッドを介して行います。
具体的な例として、以下のようなPythonのクラスを見てみましょう。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def get_name(self):
return self.name
def get_age(self):
return self.age
def set_age(self, age):
if age < 0:
raise ValueError("年齢は0以上である必要があります")
self.age = age
上記の例では、Personというクラスを定義しています。
このクラスは、nameとageという属性を持ち、get_name()メソッドとget_age()メソッドが公開されています。
一方で、set_age()メソッドはage属性の値を変更するために公開されていますが、0未満の値を入力するとValueErrorが発生します。これにより、age属性が不正な値を持つことを防ぐことができます。
継承
継承は、既存のクラスをベースに新しいクラスを作成することで、プログラムの再利用性を高める方法です。
継承によって、既存のクラスの機能を引き継ぎつつ、新しい機能を追加したクラスを作成することができます。
また、クラスの階層構造が明確になるため、プログラムの理解やメンテナンスが容易になります。
例えば、自動車クラスを継承したトラッククラスを作成するとします。
トラッククラスには、積載量といった新しい属性が必要です。
この場合、自動車クラスを継承して、トラッククラスを作成することができます。このように、既存のクラスをベースに新しいクラスを作成することで、プログラムの再利用性を高めることができます。
具体的な例として、以下のようなPythonのクラス見てみましょう。
class Vehicle:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def description(self):
return f"{self.year} {self.make} {self.model}"
class Car(Vehicle):
def __init__(self, make, model, year, num_doors):
super().__init__(make, model, year)
self.num_doors = num_doors
class Truck(Vehicle):
def __init__(self, make, model, year, payload_capacity):
super().__init__(make, model, year)
self.payload_capacity = payload_capacity
上記の例では、Vehicleというクラスを定義しています。
このクラスは、make、model、yearという属性を持ち、description()メソッドが公開されています。そして、Vehicleクラスを継承したCarクラスとTruckクラスを定義しています。Carクラスにはnum_doorsという新しい属性が追加されており、Truckクラスにはpayload_capacityという新しい属性が追加されています。
ポリモーフィズム
ポリモーフィズムは、同じメソッド名で異なる動作をすることができる機能です。
具体的には、異なるクラスで同じメソッド名を定義することで、同じメソッド名を呼び出した場合でも、各クラスで異なる動作をすることができます。
これによって、コードの再利用性を高め、プログラムの拡張性を向上させることができます。
例えば、図形をオブジェクトとして考えると、四角形と三角形の面積を計算するメソッドを考えます。四角形と三角形は異なる形状であるため、メソッドの実装が異なります。
しかし、同じメソッド名で定義することで、プログラムの拡張性を高めることができます。
具体的な例として、以下のようなPythonのクラスを見てみましょう。
class Shape:
def area(self):
pass
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
class Triangle(Shape):
def __init__(self, base, height):
self.base = base
self.height = height
def area(self):
return self.base * self.height / 2
上記の例では、Shapeという抽象クラスを定義しています。このクラスにはarea()というメソッドが定義されていますが、このメソッドは具体的な実装がなく、抽象メソッドとして定義されています。
そして、RectangleクラスとTriangleクラスを定義しています。これらのクラスでは、Shapeクラスを継承し、area()メソッドを実装しています。
Rectangleクラスでは、widthとheightを用いて面積を計算し、Triangleクラスでは、baseとheightを用いて面積を計算しています。