0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

オブジェクト指向の利点が、コード例でなんとなくわかる記事

Posted at

記事を書いた背景

オブジェクト指向(OOP)は、実際のコード例を見ると、その利点が分かりやすくなるのではないかと思い、記事にしてみました。

コード例(非オブジェクト指向)

今回はPythonで、簡単な銀行口座の機能を作ってみます。
機能は、残高確認、預け入れ、引き出し、です。
まずは、非オブジェクト指向から

non_oop.py
account_number_A=1234
password_A=12340000
zandaka_A=account_number_A*password_A

account_number_B=2345
password_B=23450000
zandaka_B=account_number_B*password_B

#すべてのアカウントの、ナンバー、パスワード、残高が入っている辞書のリスト
private_list=[{'account_number':account_number_A,'password':password_A,'zandaka':zandaka_A},{'account_number':account_number_B,'password':password_B,'zandaka':zandaka_B}]


def account_is_current(account_number, password):
    #private_listから、account_numberとpasswordが一致している要素があればTrueを返す
    for account in private_list:
        if account['account_number'] == account_number and account['password'] == password:
            return True
    return False

def bank_zandaka(account_number,password):
        for item in private_list:
            if item['account_number'] == account_number :
                print('あなたの預金残高は、'+str(item['zandaka'])+'円です')
                return True
        return False

def bank_hikidashi(account_number, password, price):
    for item in private_list:
        if item['account_number'] == account_number and account_is_current(account_number, password):
            # 残高が、引き出し額より多いか確認
            if item['zandaka'] >= price:
                item['zandaka'] -= price
                return True
            else:
                return False
    return False


def bank_azukeire(account_number, password, price):
    for item in private_list:
        if item['account_number'] == account_number and account_is_current(account_number, password):
            item['zandaka'] += price
            return True
    return False


def zandaka_kakunin(account_number, password):
    if bank_zandaka(account_number,password):
        pass
    else:
        print("不正なログインです")


def hikidashi(account_number, password, price):
    if bank_hikidashi(account_number, password, price):
        print("引き出し成功")
    else:
        print("引き出し失敗:残高不足または不正なログインです")


def azukeire(account_number, password, price):
    if bank_azukeire(account_number, password, price):
        print("預け入れ成功")
    else:
        print("預け入れ失敗:不正なログインです")

実際にこの機能を使う、runtime.pyはこちら

runtime.py
# 非オブジェクト指向
from non_oop import *

azukeire(1234,12340000,100)##預け入れ成功
hikidashi(1234,12340000,100)##引き出し成功
azukeire(2345,23450000,1000)##預け入れ成功
hikidashi(2345,23450000,2000)##引き出し成功
hikidashi(123,12300,200)##引き出し失敗:残高不足または不正なログインです
zandaka_kakunin(1234,12340000)##あなたの口座残高は、15227560000円です
zandaka_kakunin(2345,23450000)##あなたの口座残高は、54990249000円です

runtime.pyの中で、azukeire()、hikidashi()、いずれの関数を使うにせよ、いちいちナンバーとパスワードを引数に入れなければならず、不便です。
non_oop.pyについても、コードの初めの方に、それぞれのアカウントのナンバー、パスワード、残高をすべて定義しているため、コードが無駄に長く、読みにくくなっています。また、関数が同じようにいくつも配置されているため、それぞれの関数の役割が、分かりにくくなっています。

コード例(オブジェクト指向)

先ほどの例での問題点を改善すべく、クラスを用いて以下のように記述することができます。

oop.py
class Bank:
    #インスタンス生成時に実行される
    def __init__(self,*account_numbers) -> None:
        self.private_list=[]
        # アカウント情報の複数作成
        for account_number in account_numbers:
            password_i=int(str(account_number)+'0000')
            zandaka_i=account_number*password_i
            dict_i={'account_number':account_number,'password':password_i,'zandaka':zandaka_i}
            #private_listにアカウントごとの辞書型データを追加
            self.private_list.append(dict_i)


    def account_is_current(self,account_number, password):
        for account in self.private_list:
            if account['account_number'] == account_number and account['password'] == password:
                return True
        return False
    

    def bank_zandaka(self,account_number,password):
        for item in self.private_list:
            if item['account_number'] == account_number :
                print('あなたの預金残高は、'+str(item['zandaka'])+'円です')
                return True
        return False


    def bank_hikidashi(self,account_number, password, price):
        for item in self.private_list:
            if item['account_number'] == account_number :
                # 残高が、引き出し額より多いか確認
                if item['zandaka'] >= price:
                    item['zandaka'] -= price
                    return True
                else:
                    return False
        return False


    def bank_azukeire(self,account_number, password, price):
        for item in self.private_list:
            if item['account_number'] == account_number :
                item['zandaka'] += price
                return True
        return False

#2つのアカウント情報を作成したbank_insを作る(インスタンス生成)
bank_ins=Bank(1234,2345)


class Account:
    #インスタンス生成時に実行される
    def __init__(self,account_number,password) :
        #アカウントが存在しているか確認する
        if bank_ins.account_is_current(account_number,password):
            #アカウント情報定義
            self.account_number=account_number
            self.password=password
            print('アカウントは正常に作成されました')
        #存在していなければ、処理を中止
        else:
            print("不正なログインです")
            #処理を中止
            exit()

    def zandaka_kakunin(self):
        if bank_ins.bank_zandaka(self.account_number,self.password):
            pass
        else:
            print("失敗しました")

    def hikidashi(self,price):
        if bank_ins.bank_hikidashi(self.account_number,self.password, price):
            print("引き出し成功")
        else:
            print("引き出しに失敗しました。")

    def azukeire(self, price):
        if bank_ins.bank_azukeire(self.account_number,self.password, price):
            print("預け入れ成功")
        else:
            print("預け入れに失敗しました")

そして、runtime.pyがこちら

runtime.py
# オブジェクト指向
from oop import *

account_A=Account(1234,12340000)##アカウントは正常に作成されました
account_B=Account(2345,23450000)##アカウントは正常に作成されました
account_A.azukeire(100)##預け入れ成功
account_A.hikidashi(100)##引き出し成功
account_B.azukeire(1000)##預け入れ成功
account_B.hikidashi(2000)##引き出し成功
account_A.zandaka_kakunin()##あなたの口座残高は、15227560000円です
account_B.zandaka_kakunin()##あなたの口座残高は、54990249000円です
account_C=Account(123,12300)##不正なログインです

runtime.pyでは、いちいちアカウント情報を引数に入れる必要がなくなり、より直感的な記述ができるようになっています。また、アカウントのインスタンス生成時に、アカウントが存在しているかどうかを確認できる、という利点が生まれています。
oop.pyでは、関連するメソッド(関数)を同じクラス内に記述することで、それぞれの関数の役割が、より分かりやすくなっています。
Bankクラス内で、アカウント情報の作成をしているため、non_oop.pyでは最初に記述されていた情報が、すべてBankクラス内で収まることになり、コードが読みやすくなりました。アカウント情報を変えたいときは、bank_ins=Bank(1234,2345,123)などのように、一行変更するだけで良くなったことも、大きな利点です。

コード例を通して

oop.pyは、一貫して、関連する変数、メソッドを、同じクラス内に記述する、といったことがなされています。

最後に

オブジェクト指向という概念は、まだまだ奥が深く、本来は、解説すべきことがまだまだ数多くあるようです。
私もオブジェクト指向を完全に理解できているとは言えず、このようなざっくりとした解説になってしまいましたが、少しでも利点が伝わる記事になっていれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?