📌 OOP(Object-Oriented Programming, 객체 지향 프로그래밍)이란?
Object Oriented Programming의 약자로 객체의 관점에서 프로그래밍 하는것 (java, python etc)
반대 개념으로 절차 지향 프로그래밍(Procedure Programming,PP)인 C언어가 있다.
절차 지향 프로그래밍은 프로세스가 함수 단위로 순서대로 진행되는 것을 말한다.
+) 객체지향(OOP)과 절차적 프로그래밍(PP) 비교 : https://st-lab.tistory.com/151
📌 객체(Object)란?
- 구성요소 하나하나를 객체라고 한다.
- (일반적인 설명상 간단히 하자면)객체 = 대상
📌 클래스(Class)란?
- 객체들의 공통적인 속성을 모아 정의 내린것
- 코드 작성의 기본단위 이자 객체들을 찍어내는 템플릿
- 속성(attribute)와 행위(Method)를 정의
클래스(Class) = 붕어빵틀
객체(Object) = 틀로 만들어진 붕어빵
📌 OOP의 4가지 특성(추상화, 캡슐화, 상속성, 다형성)
✏️ 추상화(Abstraction)
데이터와 메소드를 클래스 하나로 묶어 메소드로 접근 할 수 있도록 하는 방법이고 목적과 관련이 없는 부분을 제거하여 필요한 부분만을 표현한다. 즉, 공통의 속성이나 기능을 묶어 이름을 붙이는 것
- 닭발, 떡볶이, 복지리, 맥주, 소주 등이 있을 때, 이들을 각각의 객체라 하며 묶으려고 하는 상황에서 음식 혹은 스트레스받을 때 생각나는 단어 등으로 크게 정의 할수 있다.
- 간단 요약 : 토끼, 고양이, 강아지,사자 etc > 동물 or 생물
🍀Tip:
1. 이름을 잘 짓자!
- 이름만 보고도 직관적으로 어디에 쓰이는지 어떻게 사용해야 할지 등을 유추가능해야한다.
2. 문서화 하자!
- 클래스, 메소드, 변수 등에 설명 부여
- class or 함수 선언부 바로 밑에 작성
+) 자세한 설명 링크 : https://wikidocs.net/16075
from abc import *
class 추상클래스명(metaclass=ABCMeta):
'''
클래스 설명
'''
@abstractmethod
def 추상메소드(self):
'''
클래스 설명
'''
pass
✏️ 상속, 재사용(Inheritance)
- 상위 개념의 특징을 하위 개념이 물려받는 것으로서 절차지향과 차이를 보여주는 항목이다.
- 코드의 중복을 없애기 위해 필요하다.
- 동물이라는 부모 클래스가 있을 때, 부모는 생명체로서 숨을 쉬고, 영양소를 섭취하는 기능을 갖고있는데, 여기서 날개를 단 객체를 생성하고 싶으면 기존에 있는 부모 클래스를 활용하여 날개를 가진 조류라는 객체를 생성한다. 그러면 생명체로서 숨을 쉬고, 영양소를 섭취하는 기능을 갖으면서 날개를 단 동물이 되는것이다.
- 부모기능 : 숨쉬기,먹기
- 자식기능 : 날개 달림
= 날개달린 숨쉬기,먹기 가능한 동물
+) 자세한 설명 링크 : https://wikidocs.net/16075
기본 형식
class 부모클래스:
...내용...
class 자식클래스(부모클래스):
...내용...
class Country: #부모클래스
"""Super Class"""
name = '국가명'
population = '인구'
capital = '수도'
def show(self):
print('국가 클래스의 메소드입니다.')
class Korea(Country): #자식클래스
"""Sub Class"""
def __init__(self, name):
self.name = name
def show_name(self):
print('국가 이름은 : ', self.name)
>>> from inheritance import *
>>> a = Korea('대한민국')
>>> a.show()
국가 클래스의 메소드입니다.
>>> a.show_name()
국가 이름은 : 대한민국
>>> a.capital
'수도'
>>> a.name
'대한민국'
메소드 오버라이딩 (Method overriding)
부모 클래스의 메소드를 자식 클래스에서 재정의 하는 것
class Korea(Country):
"""Sub Class"""
def __init__(self, name,population, capital):
self.name = name
self.population = population
self.capital = capital
def show(self):
print(
"""
국가의 이름은 {} 입니다.
국가의 인구는 {} 입니다.
국가의 수도는 {} 입니다.
""".format(self.name, self.population, self.capital)
)
... 생략
# 부모 클래스의 show()메소드는 무시되고 자식클래스의 show()메소드가 수행
>>> from inheritance import *
>>> a = Korea('대한민국', 50000000, '서울')
>>> a.show()
국가의 이름은 대한민국 입니다.
국가의 인구는 50000000 입니다.
국가의 수도는 서울 입니다.
+) 부모 메소드 호출하기
부모클래스의 메소드도 수행하고, 자식클래스의 메소드의 내용도 함께 출력하기를 원할 때, super() 라는 키워드를 사용
class Korea(Country):
... 생략
def show(self):
super().show()
print(
"""
국가의 이름은 {} 입니다.
국가의 인구는 {} 입니다.
국가의 수도는 {} 입니다.
""".format(self.name, self.population, self.capital)
)
... 생략
>>> from inheritance import *
>>> a = Korea('대한민국', 50000000, '서울')
>>> a.show()
국가 클래스의 메소드입니다.
국가의 이름은 대한민국 입니다.
국가의 인구는 50000000 입니다.
국가의 수도는 서울 입니다.
다중상속(Multiple inheritance)
상속 개수 제한 없음
class 부모클래스1:
...내용...
class 부모클래스2:
...내용...
class 자식클래스(부모클래스1, 부모클래스2):
...내용...
class Country:
"""Super Class"""
...생략
class Province:
Province_list = []
class Korea(Country,Province ):
"""Sub Class"""
... 생략
✏️ 캡슐화(Encapsulation)
불필요한 정보는 숨기고 중요한 정보만을 표현해 프로그램을 간단히만듬는 방식으로 데이터 구조와 데이터를 다루는 방법들을 결합 시켜 묶는 것이다. 그래서 캡슐화를 하면 불필요한 정보를 감출 수 있기 때문에, 정보은닉을 할 수 있다는 특징이 있다
- 사용자가 변수와 메소드에 직접적으로 접근하여 실수/고의로 데이터를 변경하는 행위를 미연에 방지하기 위해 필요하다.
- 크게 2가지 방법(Private Variable와 Protected members )이 있다.
- 변수나 메소드 앞에 _ 두 개를 붙이면 외부에서 접근 불가 ex) _ _count , _ _sum(self, number1, number2)
- 단, 특수메소드(앞뒤로 _ _붙음)는 외부에서 접근 가능
| 접근제어자 | 문법 | 의미 |
| Public | name | 외부로부터 모든 접근 허용 |
| Protected | _name | 자기 클래스 내부 혹은 상속받은 자식 클래스에서만 접근 허용 |
| Private | __name | 자기 클래스 내부의 메서드에서만 접근 허용 |
+) 자세한 설명 링크 :https://www.fun-coding.org/PL&OOP1-5.html
Private Variables(name mangling)
어떤 한 객체 변수를 다른 한 객체의 메소드를 이용해야지만 변경할 수 있게 하는 방법
class Example:
def __init__(self, name, number):
self._name = name
self._number = number
def get_name(self):
return self._name
def set_name(self, name):#name 변경 메소드 선언
self._name = name #name 값 변경
def get_number(self): #name 값 반환 메소드 선언
return self._number
def set_number(self, number):
self._number = number
student = Example("홍길동", 15)
print(Example.get_name())
print(Example.get_number())
Protected Members
클래스 외부에서 접근이 불가하고 해당 클래스 내부 하위 클래스에서만 접근하게끔 설정하는 기법
- prefix로 ‘_‘를 사용하며, Sub Class에서 사용하겠다는 의미
class Example1:
def __init__(self, name, roll, branch):
# Roll, Branch 출력 메소드 (Protected)
self._name = name
self._roll = roll
self._branch = branch
def _roll_branch(self):
# Protected data 출력
print("Roll: ", self._roll)
print("Branch: ", self._branch)
class Example2(Example1):
#Example1 상속
def __init__(self, name, roll, branch):
# Name, Roll, Branch 출력 메소드
Example1.__init__(self, name, roll, branch)
def details(self):
# Example1의 Protected 변수, 메소드
print("Name: ", self._name)
self._roll_branch()
>>> info = Example2("홍길동", "학부생", "코딩어려워학과")
>>> info._branch = "컴퓨터과학과"
>>> info.details()
Name: 홍길동
Roll: 학부생
Branch: 컴퓨터과학과
✏️ 다형성(polymorphism)
여러가지 형태가 존재한다라는 뜻으로 코딩에서는 형태가 같은데 다른 기능을 하는 것을 의미한다
- 주로 메소드 오버라이딩(Method overriding)를 사용하여 구현 한다
- 메소드 오버로딩(Method overloading)은 python 에서 정식으로 지원되지 않는다. 구현은 가능하지만 코드가 복잡하고 난해해진다.
+) 자세한 설명 링크 : https://brunch.co.kr/@kd4/4
+) 자세한 설명 링크 : https://www.programiz.com/python-programming/polymorphism
# Polymorphism in Class Methods
class Cat:
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(f"I am a cat. My name is {self.name}. I am {self.age} years old.")
def make_sound(self):
print("Meow")
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(f"I am a dog. My name is {self.name}. I am {self.age} years old.")
def make_sound(self):
print("Bark")
cat1 = Cat("Kitty", 2.5)
dog1 = Dog("Fluffy", 4)
for animal in (cat1, dog1):
animal.make_sound()
animal.info()
animal.make_sound()
>>> Meow
>>> I am a cat. My name is Kitty. I am 2.5 years old.
>>> Meow
>>> Bark
>>> I am a dog. My name is Fluffy. I am 4 years old.
>>> Bark
# Method Overriding
from math import pi
class Shape:
def __init__(self, name):
self.name = name
def area(self):
pass
def fact(self):
return "I am a two-dimensional shape."
def __str__(self):
return self.name
class Square(Shape):
def __init__(self, length):
super().__init__("Square")
self.length = length
def area(self):
return self.length**2
def fact(self):
return "Squares have each angle equal to 90 degrees."
class Circle(Shape):
def __init__(self, radius):
super().__init__("Circle")
self.radius = radius
def area(self):
return pi*self.radius**2
a = Square(4)
b = Circle(7)
print(b)
print(b.fact())
print(a.fact())
print(b.area())
>>> Circle
>>> I am a two-dimensional shape.
>>> Squares have each angle equal to 90 degrees.
>>> 153.93804002589985