Computer Science

OOP(Object-Oriented Programming)란?

Balang 2023. 5. 15. 17:06
728x90

OOP(Object-Oriented Programming)

  • 쉽게 생각해서 세상에 있는 실체가 있는 모든 물체를 클래스와 인스턴스, 함수, 변수라는 object로 변화 시켜서 프로그래을 구성한다고 생각하자
  • OOP의 기본 전제는 기능(함수, 변수) 재 사용이 가능하도록 설계 및 프로그래밍 했는지다.
  • 프로그래밍에서 사용되는 대부분의 개념은 최소비용으로 최대효율을 얻기 위해 개발되었다. OOP도 그런 개념의 일부일 뿐이다

OOP에 대한 의견

  • 중요한 것은 용어보다는, 현실에서 발생할 수 있는 특정 object를 컴퓨터라는 도구에 인식시키는 것이라 할 수 있다.
  • 대부분의 분야에서 OOP의 개념을 적용하여 프로그래밍을 수행한다.
  • 기본개념 : 설계(사람이 이해하는 방식)와 구현할 소스코드(컴퓨터가 이해하는 방식) 간의 상호이해가 중요하다.
    • HW&SW 성능증가(CPU성능 증가, 소프트웨어 다중실행) 덕분에 OOP의 모든 기능을 활용할 필요는 없다.
      • OOP의 개념을 무분별하게 활용하면 유지보수가 어려워질 수도 있기때문에 설계방향 및 서비스기능에 따라 사용해야 한다.
  • OOP의 어려운 점 :
    • OOP는 하나의 패러다임일 뿐이기 때문에 기존의 프로그래밍 패러다임(Procedural Programming, Functional Programming, ...)들과 우열을 가릴 필요는 없다.
    • OOP는 주관성이 높으므로, 보편적으로 활용되는 개념에 대해 배운다.(주관성이 높다는 뜻은 소프트웨어 서비스 설계방향에 영향을 많이 받는다.)
    • OOP를 제대로 하는 법은 프로그래밍뿐만 아니라 다양한 도메인에서 재사용 가능한 클래스, 메소드(기능) 설계가 중요하다.

  • OOP 개념이 나오기 전에는, 배열과 함수, 변수를 많이 생성하고 활용하여 최대한 많은 기능을 적은 양의 소스코드파일에 담았다.
  • 속성과 기능이 증가할 때마다 배열과 함수를 계속 생성해야했기 때문에 소스코드를 관리하는데 있어서 비효율이 발견되었다.
    • 이에 따라 속성과 기능을 object라는 최소단위로 분리하는 OOP의 개념이 나오기 시작했다.
    • 프로그래밍에서 OOP의 개념을 항상 활용하지는 않는다.
    • (데이터 분석을 진행하는 경우, 모듈과 라이브러리를 활용한 분석 인사이트가 중요하다.)

OOP를 위한 구성을 파악한다.

  • OOP를 활용할 때의 특징은 어떤 것이 있을까요?
    • PEP와 같이 여러사람과 함께 일관적인 코드맥락을 유지할 수 있습니다.
    • 복잡한 프로그래밍에 대해 함수나 클래스를 활용하여 오류발생확률을 줄일 수 있습니다.
    • 나머지는 OOP의 구성을 보면서 생각해보도록 합니다.

캡슐화

  • 기본개념 : 내부 속성(변수)과 함수를 하나로 묶어서 클래스로 선언하는 일반적인 개념
    • 캡슐화형태로 코드를 작성하지 않으면 특정 기능(함수, 변수)에 직접 접근하게 되는 상황이 된다.
    • 기능이 많아질수록 재사용의 개념을 활용하기가 어려움
    • 해당 접근제어 관련해서는 아래 콘텐츠 파이썬 활용 및 OOP에서 추가적으로 다룹니다.

상속과 포함(Inheritance & Composition)

  • object의 종류는 현실 세계에 있는 대부분이기 때문에, 설계될 수 있는 다양한 object가 있다.
  • 상속(Inheritance)
  • "개는 동물이다." 또는 "선생님은 직장인이다."라는 관계로서 설명된다. 기본개념 : 상위 클래스의 모든 기능(함수, 변수)을 재사용할 수 있다.
  • 포함(Composition)
    # 상속코드
    class Person:
        def __init__(self, name):
            self.name = name
    
    class Student(Person):      # Person 클래스 상속받음(name 변수를 파라미터로 재사용)
        def study(self):
            print (self.name + " studies hard")
    
    class Employee(Person):     # Person 클래스 상속받음(name 변수를 파라미터로 재사용)
        def work(self):
            print (self.name + " works hard")
    
    # object 생성
    s = Student("Dave")
    e = Employee("David")
    
    # object 실행
    s.study()
    e.work()
    
    # 포함코드
    
    # 클래스 선언
    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def printPerson(self, name, age):
            print('Person_printPerson', name, age)
    
    class Student:
        def __init__(self, name, age, id):
            self.person = Person(name,age)
            Person.__init__(self, name, age)
            self.id = id
    
        def test(self, score):
            if score > 80:
                return (self.person.printPerson(self.name, self.age))
            else:
                print (self.name + " needs supplementary lessons")
    
    # object 생성
    # 한 번 생성된 object는 파라미터가 변하지 않는 이상 출력값 또한 변하지 않는다.
    s = Student("Dave", 20, 1)
    
    # object 실행
    print("s.age:", s.name)   # result : Dave
    print("s.age:", s.age)   # result : 20
    print("s.id:", s.id)   # result : 1
    print('\\\\n')
    
    # 객체 하나 더 생성하기
    s2 = Student("Jamie", 25, 2)
    print("s2.age:", s2.name)   # result : Jamie
    print("s2.age:", s2.age)   # result : 25
    print("s2.id:", s2.id)   # result : 2
    print('\\\\n')
    
    # 점수입력
    print('-- test score result --')
    s.test(90)
    s2.test(11)
    
    # 포함코드
    class Bill():
        def __init__(self, description):
            self.description = description
    
    class Tail():
        def __init__(self, length):
            self.length = length
    
    class Duck():
        def __init__(self, bill, tail):
            self.bill = bill
            self.tail = tail
    
        def about(self):
            print(f"This duck has a {self.bill.description} and a {self.tail.length}.")
    
    # object 생성
    duck = Duck(Bill('bill object'), Tail('tail object'))
    
    # object 실행
    duck.about()
    
  • "개는 몸을 갖고 있다." 라는 관계로서 설명된다. 기본개념 : 다른 클래스의 일부 기능(함수)만을 재사용한다.

추상화

  • 기본개념 : 추상화(abstraction)는 복잡한 내용에서 핵심적인 개념 및 기능을 요약하는 것을 말한다.
    • object의 기능에 따라 추상클래스(상위클래스)를 상속받아 개별적으로 클래스(하위클래스)를 생성한다.
    • 기본적으로 추상메소드를 선언하며 실제 실행되는 기능은 보여지지 않는다.
    • 실제 실행되는 기능은 선언된 추상클래스를 상속받은 다른 클래스의 메소드에서 확인할 수 있다.
    • 추상클래스를 사용하는 이유
      • 클래스 또는 함수가 예상했던 것 이상으로 많이 생성되는 경우 추상클래스를 생성하여 핵심적인 기능만 생성해놓는다.
      • 실제로 동작기능은 추상클래스에서 상속받은 하위클래스의 메소드에서 진행된다.
      • 추상클래스의 추상메소드를 활용할 때 장점은 추상클래스를 중심으로 하위클래스의 메소드를 다양하게 생성할 수 있기 때문에, 유지보수를 진행하는 경우 추상클래스만 수정하면 되므로 복잡성을 낮출 수 있다.
  • 참고 : 파이썬의 추상 베이스 클래스

다형성

  • 다형성이란? 같은 종의 생물이지만, 모습이나 고유한 특징이 다양한 성질을 말한다.
  • OOP에서 다형성은 계층 구조의 상속 관계에서 상속받은 기능 외, 다른 기능을 추가적으로 제공하고자 할 때 사용한다.
    • 사용 시 장점
      • 프로그램 작성 코드량을 줄여준다.
        • 다형성을 잘 쓰면 if/else 문을 많이 줄일 수 있다
      • 코드의 가독성을 높혀준다.

클래스 설계와 사용

  • 여기서 주로 배울 것을 클래스 설계이다.
  • 클래스 설계가 중요한 이유는 코드 재사용성이다.

💡 생각하는 시간 : 아래처럼 단계별로 코드설계를 진행한다.

  • 코드설계를 진행하는데 앞서, 바로 소스코드를 작성하지 않고 그림과 글을 통해 자신의 방법으로 코드블록을 구성해본다.

1단계

  • 코드 설계 시 사용할 object부터 적어보자.
  • Users
    • Customers

2단계

  • 코드 작성 전, 각 object별로 요구되는 속성과 어떤 기능을 위해 생성되었는지 설계한다.
  • Users
    • Attributes(속성)
      • 이름
      • 사용자가 관리자인지?
    • Customers
      • Attributes
        • 이름
        • 구매목록

object간 관계에 대해 생각해본다.

  • 판매자는 1개 이상의 제품을 갖고 있다.
  • 고객은 1개 이상의 구매를 한다.
  • 구매는 1개 이상의 제품을 구매하는 것이다.

📚 Reference

728x90
반응형