オブジェクト指向プログラミングの4大要素 | Python

Python
スポンサーリンク

オブジェクト指向プログラミングの4大要素

  1. カプセル化
  2. 抽象化
  3. ポリモーフィズム
  4. 継承

カプセル化とは

カプセル化の1つ目のコンセプト
オブジェクト指向プログラミングにおいて
「オブジェクトによって複数の変数(状態を保持)とメソッド(状態を変更したり状態を使用して計算したりする)をまとめること」

オブジェクトの状態として、lengthとwidthがインスタンス変数に保持されており、これらの状態はオブジェクトという単位にまとめられていて、それはareaも同様。
オブジェクトの状態を使って四角形の面積を計算している。

class Rectangle:
    def __init__(self, w, l):
        self.width = w
        self.length = l
        
    def area(self):
        return self.width * self.length

カプセル化の2つ目のコンセプト
「データをクラス内に隠蔽して外から見えないようにすること」
クラスの外側にある利用側のコードからデータを直接操作するのではなく、メソッドを通じて操作させる。
クラスの外側からオブジェクトを利用するコードをclientと呼ぶ。

class Data:
    def __init__(self):
        self.nums = [1,2,3,4,5]
        
    def change_data(self, index, n):
        self.nums[index] = n

data_one = Data()
data_one.nums[0] = 100
print(data_one.nums)

data_two = Data()
data_two.change_data(0, 1000)
print(data_two.nums)

インスタンス変数numsをリストからタプル変えた場合

class Data:
    def __init__(self):
        #タプルに変更してみる
        self.nums = (1,2,3,4,5)
        
    def change_data(self, index, n):
        self.nums[index] = n

#タプルの要素は変更不可なのでエラーが出る        
one_data = Data()
one_data.nums[0] = 100
print(one_data.nums)

プライベート変数やプライベートメソッドといったオブジェクトの外から参照、操作ができない属性を定義できるようにして解決している。プライベートな変数やメソッドはクラス内からだけ使いたい変数やメソッドを用意した時(あるいは変更のしやすさを維持しようとした時)、プライベートであればオブジェクトの外から利用されることはないのでclientのコードを壊すような心配もない。

この逆でクラス内ぶのデータをclientから直接操作できるようにしたいときは、パブリック変数を使う。

Pythonにはプライベート変数はなく全てパブリック変数なので名前付けの規約によってアクセスに関する問題を解決している。

clientからアクセスして欲しくない変数やメソッドには名前の前にアンダースコアを一つつける。

スポンサーリンク

抽象化

抽象化とは「対象から小さな特徴を除いて、本質的な特徴だけを集めた状態」にする手順で、抽象化をオブジェクト指向プログラミングで使うのはクラスを使ってオブジェクトをモデル化する際に不要な詳細を省略すること。

例えば人をモデル化するとき、人の特徴には髪の色、目の色、身長、体重、性別など多くの特徴があるが人をクラスで表現する際に、多くの要素はこのクラスで表現する問題には関係ないので、扱いたい問題にフォーカスして本質的な特徴以外を取り除いたのが抽象表現。

ポリモーフィズム

ポリモーフィズムは、「同じインターフェースでありながらデータ型に合わせて異なる動作をする機能」をプログラミングで提供するインターフェースの関数やメソッドのこと

例:print関数は1つのインターフェースだけでstr,int,float型を返すことができる。

print('Hello World') #str
print(300) #int
print(300.0) #float

継承

クラスを作る時に他のクラスからメソッドや変数を受け継ぐ。

継承元となるクラスを「親クラス」、継承先クラスのことを「子クラス」という

#親クラスShapeを継承した、子クラスSquareを定義する
class Shape:
    def __init__(self, w, l):
        self.width = w
        self.length = l
        
    def print_size(self):
        print('幅 : {}cm で長さ : {}cm'.format(self.width, self.length))
        

#同じコードを何度も書かなくてもよくなるのでコードが削減される
#子クラスには、他のクラス定義のようにメソッドや変数を定義することができ、これらは親クラスには影響しない
class Square(Shape):
    def area(self):
        return self.width * self.length

a_square = Square(30, 30)
print(a_square.area())

メソッドオーバーライド
子クラスは親クラスのメソッドを継承していくが、このメソッド名と同じメソッドを子クラスで定義することで上書きできる。
子クラスが親クラスのメソッドを別の実装で置き換えることを「メソッドオーバーライド」という

class Shape:
    def __init__(self, w, l):
        self.width = w
        self.length = l
        
    def print_size(self):
        print('幅 : {}cm で長さ : {}cm'.format(self.width, self.length))

        
class Square(Shape):
    def area(self):
        return self.width * self.length
    
    def print_size(self):
        print(" I am {} by {}".format(self.width, self.length))

a_square = Square(30, 30)
a_square.print_size()

コンポジション
コンポジションは「has-a関係」を表し、別クラスのオブジェクトを変数として持たせること。

class Dog:
    def __init__(self, name, breed, owner):
        self.name = name
        self.breed = breed
        self.owner = owner
        
class Person:
    def __init__(self, name):
        self.name = name
        
jhon = Person('Jhone')
poti = Dog('poti', 'akita', jhon)
print(poti.owner.name)

コメント