OOP에 대해 JS코드와 함게 너무잘 설명해주신 cyranocoding님의 글을 파이썬 코드를 바탕으로 재정리해본 글입니다.!
=> https://velog.io/@cyranocoding/객체-지향-프로그래밍OOP-Object-Oriented-Programming-개념-및-활용-정리-igjyooyc6c

 

 

 

이미지출처-https://medium.com/@gwakhyoeun/oop-oriented-object-programmin-df477e49dfa0

 

OOP(객체 지향 프로그래밍)이란?

객체 지향 프로그래밍은 컴퓨터 프로그램을 객체(Object)들의 모임으로 파악하고자 하는 프로그래밍의 패러다임 중에 하나이다. 각 객체들은 서로 메시지를 주고 받을 수 있으며 데이터를 처리할 수 있다.

객체 지향 프로그래밍의 장점은

  • 프로그램을 유연하고 변경이 용이하게 만든다.
  • 프로그램의 개발과 보수를 간편하게 만든다.
  • 직관적인 코드 분석을 가능하게 한다.

위의 장점들을 관통하는 객체 지향 프로그래밍의 중요한 특성은 강한 응집력과 약한 결합력을 지향한다는 점이다.

소프트웨어 공학에서 말하는

 

응집력 : 프로그램의 한 요소가 해당 기능을 수행하기 위해 얼마만큼의 연관된 책임과 아이디어가 뭉쳐있는지를 나타내는 정도 프로그램의 한 요소가 특정 목적을 위해 밀접하게 연관된 기능들이 모여서 구현되어 있고, 지나치게 많은 일을 하지 않으면 그것을 응집력이 높다고 표현한다.

 

⇒ 특정 목적을 위해 연관된 기능들을 한 요소(객체)에 모아서 구현,

지나치게 많은일을 하지않으면 응집력이 높다!!! ⇒ 한요소가 한가지의 일을 하면 응집력이 높다

 

 

결합력: 프로그램 코드의 한 요소가 다른것과 얼마나 강력하게 연결되어있는지, 얼마나 의존적인지를 나타내는 정도. 결합력이 낮다는 것은 한요소가 다른 요소들과 관계를 크게 맺고 있지 않은 상태를 의미한다.

 

⇒ 얼마나 의존적인지를 나타내는 정도 ⇒ 독립적일 수록 객체지향적

 

OOP의 경우 클래스에 하나의 문제해결을 위해 데이터를 모아 놓은 객체를 활용한 프로그래밍을 지향하므로 응집력을 강화하며, 클래스 간에 독립적으로 디자인함으로써 결합력을 약하게 할 수 있다.

필드에 몬스터들을 배치하고 싶다 몬스터의 종류는 드래곤, 좀비, 해골이 있다. 각 몬스터들은 시간이 흐르고 레벨업을 할 수 있다. 위의 상황에서 객체들을 어떻게 디자인해야 할까?

필드에 몬스터들을 배치하고 싶다
몬스터의 종류는 드래곤, 좀비, 해골이 있다.
각 몬스터들은 시간이 흐르고 레벨업을 할 수 있다.
위의 상황에서 객체들을 어떻게 디자인해야 할까?

 

 

 

 

 

 

OOP의 기본 구성 요소

  • 클래스

    같은 종류의 집단에 속하는 속성과 행위를 정의한 것.

    다른 클래스와 독립적으로 디자인해야한다.

    위의 예제에서 몬스터의 특성과 행위들을 정의한 객체가 클래스가 될것이다.

  • 객체

    클래스의 인스턴스. 상위 클래스의 속성을 가지고 있으면서 개별적인 특성과 행위(메소드: method) 또한 가지고 있다.

    위의 예제에서는 드래곤, 좀비, 해골 등이 각각의 객체가 된다.

  • 메서드

    클래스로부터 생성괸 객체를 사용하는 방법. 객체의 속성을 조작하는데 사용된다.

    위의 예제에서는 각각의 몬스터들이 레벨업을 하는 행위가 메서드(method)라고 볼 수 있다.

몬스터를 만들어 봅시다.

몬스터는 체력(healthPoint)과 레벨(level), 서식지(habitat) 속성을 가지고 있으며,
레벨을 1단계 올릴 수 있는 메소드(levelup)를 가지고 있다.

이 특성들은 모든 몬스터들이 가지는 특성이므로 몬스터라는 클래스의 속성으로 부여해 줄 수 있다.

아래는 몬스터 객체를 만드는 python 코드이다.

class Monster:
        self.level = 0
        self.habitat = 'forest'

        def levelup(self):
                self.level += 1

자 이제 몬스터를 만들 수 있다. 그런데 이 몬스터에 다양한 다른 작업들을 하고 싶다.

OOP의 컨셉을 설명하면서 다양하게 조작해보고자 한다.

 

 

 

 

OOP의 장단점

장점

- 코드의 재사용성이 높아진다.

- 유지보수가 쉽다.

- 코드가 간결해진다.

 

단점

- 처리 시간이 비교적 오래 걸린다.

- 프로그램을 설계할 때 많은 고민과 시간을 투자해야한다.

 

 

 

 

OOP의 특성

캡슐화

캡슐화는 객체의 데이터를 외부에서 직접 접근하지 못하게 막고, 함수를 통해서만 조작이 가능하게 하는 작업이다.

몬스터의 레벨과 같은 경우는 이용자가 임의로 조작하게 하면 문제가 생길 가능성이 있다.

그래서 레벨업이라는 함수를 통해서만 레벨이 조작되었으면 좋겠다.

아래의 코드는 외부에서 level변수에 직접 접근하지 못하도록 막는 캡슐화를 나타내었다.

class Monster:
    self.__level = 0
    self.habitat = 'forest'

    def levelup(self):
            self.__level += 1

    def get_level(self):
            return self.__level

이런식으로 더블 언더스코어를 사용해서 private처럼 활용하여

클래스외부에서는 __level속성에 접근할 수 없다.

⇒ 캡슐화 해버리기~

 

 

 

추상화

추상화는 객체들이 가진 공통의 특성들을 파악하고 불필요한 특성들을 제거하는 과정을 말한다.

객체들이 가진 동작들을 기준으로 이용자(여기서 이용자는 객체를 구현X 사용하는 사람을 말함)들이 동작만 쉽게 구동할 수 있도록 한다.

몬스터의 예제에서 레벨업(levelUp) 메소드를 실행만 하면 level이라는 속성을 컨트롤 할 수 있었던 것처럼.

이러한 추상화 과정을 통해 이용자들은 프로그래머가 만든 객체를 더쉽게 사용할 수 있게 된다.

추상화를 할 때 주의할 점은 속성위주가 아닌 동작 위주로 정의하는 작업을 하는 것이다.

객체의 동작에 연관이 되지않는 속성들은 결국은 불필요하다. 따라서 불필요한 속성들을 걸러내기 위해 동작을 먼저 정의하고 동작에 필요한 속성들을 정리하는 것이 좋다.

 

몬스터들이 공격을 받아 healthpoint가 0이 되면 필드에서
죽은 것(death)으로 처리하고 싶다.
이용자들은 몬스터들을 공격하고 죽는 모습을 보기만 하면된다.
어떠한 과정을 거쳐서 몬스터가 죽었는지에 대해서는 알 필요가 없다

 

위의 케이스에서는 객체에 2가지 속성이 추가되어야 한다. 몬스터가 죽은상태인지 살아있는 상태인지를 확인하는 속성, 그리고 healthpoint라는 속성이다. 위의 속성을 추가하고 공격을 받는 상황을 메소드(method)로 만들어 보겠다.

class Monster:
    self.__level = 0
    self.habitat = 'forest'
    self.healthpoint = 100
    self.islive = True

    def levelup(self):
            self.__level += 1

    def get_level(self):
            return self.__level

    def damaged(self, damage):
            self.healthpoint -= damage
            if self.healthpoint <= 0:
                self.islive = False

이제 몬스터는 체력을 가지고 있고 데미지를 받아 체력이 깍아지다가 체력이 0이 되면 죽는다.

이렇게 어떠한 동작과 속성을 정의하고 불필요한 정의들을 삭제하여 이용자가 편리하게 객체를 이용할 수 있도록 구성한 것이 추상화이다.

 

 

 

 

 

+α 재사용성

몬스터를 여러 마리 만들어야 한다.

각 몬스터들은 모두 같은 속성을 가지고 있다.

몬스터 객체를 이용하여 모든 몬스터들이 같은 속성과 메소드를 가질 수 있도록 만들 수 있다.

OOP의 가장 큰 특성 중 하나가 바로 코드의 재사용성과 상속의 개념이다.

같은 객체를 여러 개 만들어야 하는 경우, 한 번 작성된 코드를 활용하여 동일한 객체를 만들 수 있다.

python 클래스에는 인스턴스 생성과 동시에 자동으로 호출되는 메서드인 생성자가 존재합니다.

 

__init__(self)

위의 __init__생성자를 활용하여 재사용성을 유지하면서 여러 객체를 생성할 수 있다.

 

class Monster:
    def __init__(self):
        self.__level = 0
        self.habitat = 'forest'
        self.healthpoint = 100

    def levelup(self):
        self.__level += 1

    def get_level(self):
        return self.__level


Goblintest = Monster()
trolltest = Monster()

위의 생성자 함수를 이용하여 각각의 몬스터 종류를 생성할 수 있다.

 

 

 

 

 

상속

  • 자식 클래스가 부모 클래스의 특성과 기능을 물려받는 것
  • 기능의 일부분을 변경하는 경우 자식 클래스에서 상속받아 수정 및 사용함
  • 상속은 캡슐화 유지, 클래스의 재사용이 용이하도록 해준다.

아래는 몬스터 class를 상속받은 Goblin, troll의 healthpoint 속성을 수정하고 확인해본 소스코드입니다.

ex)

class Monster():
    __level = 0
    habitat = 'forest'
    healthpoint = 100

    def levelup(self):
        self.__level += 1

    def get_level(self):
        return self.__level


class Goblin(Monster):
    healthpoint = 50
    print('Goblin creation')


class troll(Monster):
    healthpoint = 150
    print('troll creation')

Goblintest = Goblin()
trolltest = troll()

print(Goblintest.get_level(), Goblintest.habitat, Goblintest.healthpoint)
Goblintest.levelup()
print(Goblintest.get_level(), Goblintest.habitat, Goblintest.healthpoint)

print('------------\n')


print(trolltest.get_level(), trolltest.habitat, trolltest.healthpoint)
trolltest.levelup()
print(trolltest.get_level(), trolltest.habitat, trolltest.healthpoint)

 

 

 

 

 

다형성

  • 어떤 변수 메소드가 상황에 따라 다른 결과는 내는 것

  • 같은 모양의 코드가 다른 동작을 하는 것

  • 오버로딩 : 하나의 클래스에서 메소드의 이름이 같지만, 파라메터가 다른것

⇒ 즉 이러한 경우에는 메소드의 이름이 중복적으로 겹치게 되면서 매개변수 타입 or 매개변수의 개수에 따라서 선택적으로 메소드를 선택하게 된다.

사실, 파이썬에서는 아예 오버 로딩 기능이 없기 때문에 (가장 마지막에 쓰여지는 메소드만 기능함) 필요 없는 개념이긴 하지만, 다른 개발 툴에서는 이러한 개념도 쓰임으로 알아둘 것!

 

 

  • 오버라이딩 : 부모 클래스의 메소드를 자식 클래스의 용도에 맞게 재정의하여 코드의 재사용성을 높임

ex) 각 클래스마다 work메소드의 동작이 다르다.

# 클래스 선언
class Person:
    def __init__(self, name):
        self.name = name

    def work(self):
        print (self.name + " works hard")        

class Student(Person):
    def work(self):
        print (self.name + " studies hard")

class Engineer(Person):
    def work(self):
        print (self.name + " develops something")


student1 = Student("Dave")
developer1 = Engineer("David")
student1.work()
developer1.work()

 

 

 

 

 

 

참조

https://wikidocs.net/1740

https://medium.com/@chs99051868/python-design-pattern-factory-method-ab38db86743f

https://1022yk.tistory.com/6

https://velog.io/@cyranocoding/객체-지향-프로그래밍OOP-Object-Oriented-Programming-개념-및-활용-정리-igjyooyc6c

https://nowonbun.tistory.com/660

https://yamalab.tistory.com/28

https://wikidocs.net/16073

https://velog.io/@ygh7687/OOP의-5원칙과-4가지-특성

반응형

'python' 카테고리의 다른 글

[python] 이터레이터와 제너레이터  (0) 2021.02.20
[python] lambda expression(람다 표현식)  (0) 2021.02.19
[python] Decorator(데코레이터)  (0) 2021.02.18
[python] Closure(클로저 )  (0) 2021.02.17
[python] class, instance, Method  (0) 2021.02.11

+ Recent posts