OOP 002 | OOP(Object Oriented Programming)

This Is Empty.·2021년 12월 9일
0

OOP

목록 보기
2/2
post-thumbnail

Github Repository : https://github.com/WE-Learning-CS/OOP/tree/main/01_OOP

1. OOP(Object Oriented Programming)란?

객체지향프로그래밍은 시스템을 컴퓨터 명령어의 목록으로 구성하지 않고 여러 다양한 객체들의 집합으로 구성하는 것을 말한다. 프로그램을 객체(object)라는 기본 단위로 나누고 객체들의 상호작용으로 기능들을 구현하는 방식이다.

객체지향프로그래밍은 개발자들이 조작하기 위해 필요한 로직보다는 조작하고자 하는 객체에 초점을 맞추기때문에 규모가 크고 복잡하며 능동적으로 업데이트되거나 유지되는 프로그램에 적합하다.

핵심

  • 독립적인 객체들의 집합을 통하여 객체들이 서로 상호작용을 하는 구조로 전체 프로그램이 구현될 수 있도록 하는 것
  • 로직에 구조를 더하기 위해 OOP를 사용

왜 OOP를 사용해야 하나?

객체지향은 필요에 의해서 생겨났다. 객체지향 이전에는 기능 구현을 위한 로직을 처음부터 끝까지 나열하는 방식으로 소스코드 파일의 위에서부터 아래로 실행한 후 마지막 결과를 나타내는 단순한 구조의 프로그래밍을 주로 사용했다.

구조가 단순하다보니 프로그래밍을 하기에는 쉬웠지만 전체적인 구조가 정리되지 않고 유지보수의 난이도가 높아졌다. 코드에는 기능구현만을 위한 로직이 존재하고 구조가 존재하지 않으니 코드가 서로 꼬이는 스파게티 코드가 되는 경우가 자주 발생했다.

이런 문제를 해결하기 위해 나온 것이 로직에 구조를 더한 객체지향프로그래밍이다.

핵심 이유

  • 유지보수 용이: 기능별로 구현되어 있기 때문에 일부가 고장나도 해당 부분만 고치면 된다.
  • 재활용 용이 : 정의한 class를 상속하고 확장하여 재사용할 수 있음
  • 가독성이 좋아진다

객체지향의 장단점으로는 다음과 같다.

  • 장점
    1. 코드의 재사용이 용이하다. 코드는 상속을 통해 재사용이 가능하다. 즉 같은 코드를 여러번 작성할 필요가 없다.(생산력도 높아진다)
    2. 모듈화, 캡슐화로 유지보수가 쉽다
    3. 캡슐화 및 추상화를 사용하여 복잡한 코드를 숨기고 보호가 가능하기때문에 보안면에서 좋다.

  • 단점
    1. 객체가 많으면 용량이 증가한다. 속도가 상대적으로 느리다.
    2. 코드를 이해하기 쉽게 만드는 설계 과정에서 많은 시간과 노력이 필요하다.

OOP의 구조

  • class : 개별 개체, 속성 및 매서드의 청사진 역할을 하는 사용자 정의 데이터 유형
  • object : 특별히 정의된 데이터로 만들어진 클래스의 인스턴스
  • method : 객체의 동작을 설명하는 클래스 내부에 정의되는 함수
  • attribute : 객체의 상태

OOP의 주요 원칙

  • 캡슐화(Encapsulation)
  • 추상화(Abstraction)
  • 상속(Inheritance)
  • 다형성(Polymorphism)

1. 캡슐화(Encapsulation)

캡슐화는 연관있는 변수와 함수를 하나의 단위로 묶는 것을 말하며 모든 중요한 정보가 객체 내부에 포함되어 있고, 선택된 정보만 노출된다는 것을 말한다. 이를 통해 내부의 기능 구현이 변경되더라도 그 기능을 사용하는 코드는 영향을 받지 않도록 만들어준다. 즉, 내부 구현 변경의 유연함을 주는 것이 캡슐화이다.

다음은 캡슐화 예시 코드이다.

class Car:
    def __init__(self, model, color, year):
      self.model = model
      self.color = color
      self.year  = year

    def drive(self, speed):
      if speed != 0:
        return f'The speed of the car is {speed}.'

    def stop(self):
      return "The car has stopped."

자동차와 관련된 변수와 함수가 묶여있는 클래스 자체가 캡슐화의 예시라고 할 수 있다.

캡슐화 규칙

  • Tell, Don't Ask
    데이터를 물어보지 않고, 기능을 실행해 달라고 말하라는 규칙

  • 데미테르의 법칙
    메서드에서 생성한 객체의 메서드만 호출
    파라미터로 받은 객체의 메서드만 호출
    필드로 참조하는 객체의 메서드만 호출

정보 은닉(Information Hiding)

  • 속성이나 메소드같이 객체가 소유하는 것들을 다른 객체에 공개하지 않고 숨기는 것
  • 외부 객체가 특정 객체의 데이터와 함수를 직접 접근하여 사용하거나 변경하지 못하므로 유지 보수와 소프트웨어 확장시 오류를 최소화

보통 java에서 메소드의 공개 범위를 access modifier(접근 제어자)로 결정한다.

  • public : 해당 클래스의 객체, 상속받는 클래스의 객체, 그리고 외부 객체 모두 다 접근 가능
  • private : 해당 클래스의 객체 내부에서만 접근 가능, 상속받는 sub class도 직접적인 접근은 할 수 없고 상속받지 않는다.
  • protected : 외부 객체는 접근할 수 없다. 상속받는 sub class는 접근 할 수 있고 상속받을 수 있다.

파이썬에서는 위와 같은 접근제어자를 직접적으로 제공하지 않는다.

파이썬에서의 protected는 _(single underscore)를 통해 구현할 수 있다.
실제 제약되지는 않고 일종의 경고 표시로 사용된다.

  class Car:
      def __init__(self, name, price):
          self.name = name
          self._price = price

파이썬에서는 __(double underscore)를 통해 private를 구현할 수 있다.

  class Car:
      def __init__(self, name, price):
          self.name = name
          self.__price = price

price 필드를 비공개 속성으로 만들었기 때문에 외부에서 접근 시 위와같은 에러가 발생한다.

비공개 속성에 접근할 수 있는 방법은 java와 마찬가지로 클래스 안의 메서드를 통해 접근이 가능하다.
--> private 생성자를 만들고 getter, setter를 통해서 접근하는 것과 마찬가지.

  class Car:
      def __init__(self, name, price):
          self.name = name
          self.__price = price

      def discount(self, percent):
          self.__price = self.__price - (self.__price * percent)
          return f'discounted price = {self.__price}'

메서드도 __(double underscore)를 통해 비공개로 만들 수 있다.

class Person:
	def __greeting(self):
		print("hello")
	def hello(self):
		self.__greeting()

2. 추상화(Abstraction)


출처 : JavaScript ES7 OOP. Abstraction. Class. #1 - YouTube
youtube.com

추상화는 데이터나 프로세스 등 의미가 비슷한 개념이나 표현으로 정의하는 과정이다.

파이썬에서 추상클래스를 구현하기 위해서는 반드시 abc모듈을 import 해야한다.

from abc import *
class AbstractClass(metaclass=ABCMeta):

    @abstractmethod
    def method1(self):
        pass

추상 메소드는 생략하면 기본적인 클래스 기능은 동작하지만 추상 메소드를 추가한 후에 객체를 생성하면 에러가 발생한다.

3. 상속(Inheritance)

상속은 자식클래스(Sub Class)가 부모클래스(Base Class, Super Class)로부터 Property와 Method들을 상속받을 수 있는 특성을 말하며 한 타입을 그대로 사용하면서 구현을 추가할 수 있도록 해주는 방법을 제공한다.

class Car:
  def __init__(self, model, color, year):
    self.model = model
    self.color = color
    self.year  = year
    
  def drive(self, speed):
    if speed != 0:
      return f'The speed of the car is {speed}.'
    
  def stop(self):
    return "The car has stopped."

class Truck(Car):
    def __init__(self, name):
        self.name = name

    def load(self, baggage):
        return f"Loaded {baggage} into the truck."

위와 같이 Car class를 상속받은 Truck class가 있다고 가정했을때 Truck class에는 정의되어 있지 않지만 다음과 같이 Car class에 정의되어 있던 drive, stop 메소드를 사용할 수 있다. 또한 상속받은 클래스의 기능 뿐 아니라 새로운 기능도 추가할 수 있다.

truck = Truck("Poter")
truck.drive(100) # The speed of the car is 100.
truck.stop() # The car has stopped.
truck.load("box") # Loaded box into the truck.

4. 다형성 (Polymorphism)

다형성은 한 객체가 여러가지(Poly) 모습(morph)을 갖는다는 것을 의미한다. 여기서 모습이란 타입을 뜻하는데, 즉 다형성은 한 객체가 여러가지 타입을 가질 수 있다는 것을 뜻한다.

클래스의 다형성을 보기 전에, 우리는 len()메소드가 다음과 같이 여러 모습으로 사용되는 것을 이미 알고있다.

출처 : https://www.programiz.com/python-programming/polymorphism

len()은 str, list, dict와 같은 많은 데이터 유형에 쓰여질 수 있다.

파이썬은 다른 클래스가 같은 이름의 메서드를 가질 수 있도록 허용한다. 이도 다형성의 한 예이다.

class Car:
  def __init__(self, model, color, year):
    self.model = model
    self.color = color
    self.year  = year
    
  def drive(self, speed):
    if speed != 0:
      return f'The speed of the car is {speed}.'
    
  def stop(self):
    return "The car has stopped."


class Motorcycle:
    def __init__(self, model, color, year):
        self.model = model
        self.color = color
        self.year  = year
        
    def drive(self, speed):
        if speed != 0:
            return f'The speed of the motorcycle is {speed}.'
        
    def stop(self):
        return "The motorcycle has stopped."

또한 overiding처럼 부모 클래스의 메소드가 자식 클래스에서 변형되어 다양한 기능으로 나타날 수 있는것도 한 예시이다.

참고로 overloading처럼 이름은 같지만 인수가 다른 여러 메서드를 만드는 방법은 python에서는 지원하지 않는다

참고
object-oriented programming (OOP)
class 정리 - 추상클래스(abstract class)
Polymorphism in Python

profile
Convinced myself, I seek not to convince.

0개의 댓글