3 분 소요

객체지향 프로그래밍 (OOP : Object Oriented Programming)

  • 프로그램을 명령어의 나열로 보는 시각에서 벗어나 여러 개의 독립된 단위인 “객체”들의 모임으로 파악하는 것으로 클래스, 속성, 메서드로 구성을 이루고 있다.
  • 객체지향은 캡슐화(Encapsulation), 추상화(Abstraction), 상속성(Inheritance), Ploymorphism(다형성) 4가지의 특징으로 구성된다.

클래스의 구성

예제설명
class Car:
    def __init__(self):
        self._speed = 0
        print('\n인스턴스 성공: 자동차 객체 생성!')
    def get_speed(self):
        return self._speed
    def start(self):
        self._speed=10
        print('자동차 출발')
    def accelerate(self):
        self._speed += 20
        print('자동차 가속')
    def stop(self):
        self._speed=0
        print('자동차 정지')
        
나의차 = Car()
나의차.start()
나의차.accelerate()
print('현재속도:', 나의차.get_speed())
나의차.stop()
    
__init(self)__ 메서드:
__으로 시작하는 메서드를 매직메서드 또는 특별메서드라고 함
객체가 처음 생성될 때 자동으로 호출되는 메서드|
self 는 객체를 가리키며 첫 번째 인자로 가져야 함
_speed 속성:
_으로 시작하는 속성은 private으로 외부에서 접근이 제한된다
※ one underscore : 외부에서 변경가능, two underscore : 외부에서 변경불능
클래스 이름은 코딩규약에 따르면 주로 대문자로 시작한다.
클래스 안에 변수를 접근 하려면 클래스일름.변수 : print(나의차._speed)
type( {1:'아버지', 2:'어머니'})
dict
    
내장형(Built-in)/사용자 정의 클래스

클래스내 메서드 종류

예제설명
# ※ self 와 cls의 차이는 오직 메소드 타입에 있다. 
    # instance 메소드 사용시 self, class 메소드는 cls
    class Circle:
    __PI = 3.141592
    @classmethod
    def 원면적(cls, r): 
        x = cls.__PI*(r**2)
        return round(x,4)
    
클래스메서드 : 객체생성 없이 바로 접근 가능
Circle.원면적(3)
class Circle:
    @staticmethod
    def 원면적(r, pi): 
        x = pi*(r**2)
        return round(x,4)
정적메서드: 객체생성 없이 바로 접근 가능
Circle.원면적(3, 3.1415)
__init__()
__repr__() ...
특별 메서드 (매직 메서드)
클래스에서 자동으로 또는 특별한 연산으로 호출되는 메서드로 ‘__’ 으로 시작

특징1: 캡슐화(encapsulation)

  • 객체 외부에서 내부의 속성을 직접 접근, 속성을 읽거나 변경시키지 못하게 하는 것을 의미
  • 허락된 인터페이스/외부에 공개된 메서드를 통해 읽고 변경이 가능
  • 밑줄이 없으면 공개모드(public), 밑줄하나(protected)-변경가능하나 변경하면 안됨, 밑줄두개 (private)-변경불가
  • 캡슐화의 원칙은 밑줄 하나 이다.
  • property 기능 - 캡슐화를 유지하면서 쉽게 속성을 읽고 설정하는 방법
방법1- @ 활용법방법2-property 함수
#데코레이터 활용
class Radio:
    def __init__(self):
        self._state = 'off'
        print('인스턴스 성공 : 라디오 객체 생성!')
    @property
    def switch(self):
        return self._state
    @switch.setter
    def switch(self,value):
        self._state = value
        print('바뀐 라디오 상태:', value)
    
radio.switch = 'on'    
    
#property 함수 활용
class Radio:
    def __init__(self):
        self._state = 'off'
        print('라디오 객체 생성!')
    def read_state(self):
        return self._state
    def assign_state(self,value):
        self._state = value
        print('변경된 상태:', value)
    # property(fget=read_state,fset=assign_state ) 원래 문법이다        
    스위치=property(read_state, assign_state)

라디오.스위치='켜짐'    
    

특징2: 상속성(inheritance)

  • 클래스를 처음부터 새롭게 만들지 않고 기존의 클래스를 활용하여 수정,보완 하여 새로운 클래스를 정의
  • 상속을 원하지 않은 경우: ‘__’으로 시작하는 protected 모드로 속성 정의
# 예제
class Animal(object):  # class Animal: 와 동일한 문장임
    def __init__(self,legs=4,animal_type='beast'):
        self.legs=legs
        self.animal_type = animal_type
    def printleg(self):
        print('childleg');

# 부모의 init 이 세팅이 안되면 에러가 발생함에 주의
class Dog(Animal):
    # **kwargs(keword arguments) 함수 인자 전달 방식을 이용하여 간편히 상속
    def __init__(self,name=None,owner=None, **부모인자): 
        super(Dog,self).__init__(**부모인자) # super().__init__(**부모인자) 동일함
        print(부모인자)
        self.name = name
        self.owner = owner
    def printleg(self):       # 메서드 오버라이드 (재정의)
        print('childleg');    
    def printname(self):      # 신규 메서드 추가
        print('신규메서드');          

특징3: 다형성(polymorphism)

  • 객체가 인터페이스를 통해 다양한 동작을 제공해야 한다는 원칙
# 예시
class Animal:
    def __init__(self,name):
        self._name=name
    def talk(self):
        return (self._name[0:2]+', '+self._name[0:2])

# __init__ 가 지정되지 않기 때문에 Animal이 호출이 된다    
class Cat(Animal):
    def talk(self): # override
        return '야아옹~~'
    
# __init__ 가 지정되지 않기 때문에 Animal이 호출이 된다        
class Dog(Animal):
    def talk(self): # override
        return '멍, 멍~'
    
애완동물 = [Cat('나비'), Dog('삽살이'), Cat('미미'), Animal('구렁이')] # 리스트 정의
# index i 가 객체를 나타내게 된다.
for i in 애완동물:
    print(i._name + ': ' + i.talk())

>>> 결과 : 나비: 야아옹~~ 삽살이: 멍, 멍~ 미미: 야아옹~~ 구렁이: 구렁, 구렁

특징4: 추상성 (abstraction)

  • 기능의 세부적인 복잡성을 숨기고 객체의 주요 기능만 보여줘야 한다는 원리
  • 추상 클래스 (abstract class)
    • 구현되지 않은 추상 메서드를 한 개 이상 가지며, 자식클래스에 구현하도록 강제
    • 상속받은 클래스는 추상 메서드를 구현하지 않아도, import할 때까지 에러는 발생하지 않으나 객체를 생성할 때 에러 발생 ( 상속만 가능, 객체화 불가능! )
    • 반드시 abc 모듈을 import 해야 함
    • 사용법
      from abc import *
      class 추상클래스_이름(metaclass=ABCMeta)
          @abstractmethod
          def 추상메서드_이름(self)
              pass
      
  • 예시
from abc import *
class AbstractCountry(metaclass=ABCMeta):
    name='국가명'
    population='국가명'    
    capital='수도'      
    def show(self):
        print('국가 클래스의 메소드 입니다.')
    @abstractmethod
    def show_captial(self):        
        print('국가의 수도는 ? ',end='')
        
class Korea(AbstractCountry):
    def __init__(self, name, population, capital):
        self.name = name
        self.population = population
        self.capital = capital
    def show_name(self):
        print('국가 이름은 :', self.name)
    def show_captial(self):  # 추상 메서드를 구현해 준다
        super().show_captial()
        print(self.capital)
        
b = Korea("대한민국", 50000000, '서울')
b.show_captial() # 결과는 아래처럼 출력
국가의 수도는 ? 서울

a = AbstractCountry()  # 추상메소드가 정의 되지 않기 때문에 에러 발생

댓글남기기