본문 바로가기
개발 Tools/파이썬_개념

객체지향 프로그래밍의 특징 (추상화, 캡슐화, 상속성, 다형성, 접근지정자)

by 전컴반 2021. 9. 11.
반응형

객체 지향 프로그래밍 언어(object oriented programming) 컨셉은 명확히 알아야 한다. 객체지향 프래그래밍의 특징은 크게 추상화, 캡슐화, 상속성, 다형성이 있다. 차근차근 알아보겠다. 그전에 클래스와 객체라는 개념을 알고 넘어가자 

 

 

클래스와 객체

 

클래스

- 속성과 행위를 변수와 메서드로 정의한 논리적 개념

- 변수 : 클래스 변수(인스턴스 변수 사이에 공유되는 값, 생성사 위에 선언해준다), 인스턴스 변수(self.x....)

- 메서드 : 생성자, 일반 매소드, 소멸자

 

객체

- 클래스의 정의를 기반으로 실제 메모리에 할당된 물리적 실체

 

클래스는 논리적 개념, 객체는 물리적 실체라는 게 와닿지 않을 것이다. 예를 들면, 스마트폰이라는 클래스를 만든다. 스마트폰이라는 논리적 개념이 구체화되는 건 "아이폰", "갤럭시"로 명명됐을 때, 실체가 된다.

 

스마트폰

-이름
-색상
-제조사
-아이폰
-검은색
-애플
-갤럭시
-흰색
-삼성

 

스마트폰은 클래스, 아이폰과 갤럭시는 객체이다. 이런 식으로 클래스와 객체를 볼 수 있다.

 

 

추상화 

 

객체들의 공통 속성과 행위를 추출하는 것이다. 컴퓨터를 예로 들면, ram, ssd, cup 등등은 다 가지고 있는 속성이고 주소를 연결하고 프로그램을 실행하는 건 공통된 행위이다. 삼성 노트북이 실행하는 기능을 정의하는 게 아니라, 삼성 노트북이든, 맥북이든, 데스크톱이든, 컴퓨터라면 공통적으로 가지고 있는 속성과 행위를 추출하는 걸 추상화라 한다.

 

코드를 보겠다. 

 

class Computer:

    def __init__(self, ram, ssd, hdd, cpu, name, color, category):
        self.__ram = ram  # private 외부에서 변경 불가
        self.__ssd = ssd  # private
        self.hdd = hdd
        self.cpu = cpu
        self.name = name
        self.color = color
        self.category = category

    def connect_web(self, url):
        print(f"{url} 주소로 연결되었습니다.")

    def sw_exe(self, sw):
        print(f"{sw} 프로그램이 실행되었습니다.")
        
    @property  # 현재 self.__ram의 데이터르 갖고오고 싶으면 이렇게 사용하여 가져올 수 있다
    def ram(self):
        return self.__ram

    @ram.setter  # 인스턴스 변수 이름.setter
    def ram(self, ram):
        print(f"{self.__ram}의 (RAM)크기가 {ram}으로 변경.")
        self.__ram = ram

    @property
    def ssd(self):
        return self.__ssd

    @ssd.setter
    def ssd(self, ssd):
        print(f"{self.ssd}의 (SSD)크기가 {ssd}으로 변경.")
        self.__ssd = ssd

    def __del__(self):
        print(f"{self.name} 종료합니다")

 

이처럼 모든 컴퓨터에는 ram, ssd, cup 등등 이 필수적으로 있다. 이런 기능들을 추상화하여 생성한 것이다.

 

 

캡슐화

 

- 속성과 행위를 목적에 적합하게 묶어서 독립된 단위로 구성하는 것이다. 목적에 따라 원하는 변수나 메서드를 따로 묶을 수 있다. 

- 정보은닉: 속성과 행위에 대한 접근을 제한한다. 접근 지정자를 이용하여 외부 접근의 접근성을 설정한다.

- 결합도는 낮으면 좋은데 결합도란, 메서드가 다른 메서드에 의존하는 정도이다

- 응집도는 높으면 좋은데 응집도란, 메소드 내부 요소들의 관련 정도를 나타낸다

 

두 번째 말한 접근 지정자에 대해 자세히 보자면 말 그대로 접근에 제한을 둔다는 것이다. 자바를 배웠다면 다들 아실 것이다.

 

사용예 타입 의미
name public 정의된 클래스 내부 뿐만 아니라 외부에서도 사용 가능
_name protected 상속 클래스 및 클래스 내부에서만 사용 가능
__name private 클래스 내부에서만 사용 가능

 

위에 코드를 보면 ram과 ssd를 private로 지정하여 외부에서 접근에 제한을 뒀다. 이럴 때 접근을 조금 쉽게 하기 위해 데코레이션을 해준다.

 

class Computer:

    def __init__(self, ram, ssd, hdd, cpu, name, color, category):
        self.__ram = ram  # private 외부에서 변경 불가
        self.__ssd = ssd  # private
        self.hdd = hdd
        self.cpu = cpu
        self.name = name
        self.color = color
        self.category = category

    def connect_web(self, url):
        print(f"{url} 주소로 연결되었습니다.")

    def sw_exe(self, sw):
        print(f"{sw} 프로그램이 실행되었습니다.")

    # private 는 외부에서 바로 접근이 안되기 때문에 setter , getter 를 사용하여 접근한다
    @property  # 현재 self.__ram의 데이터를 갖고오고 싶으면 이렇게 사용하여 가져올 수 있다
    def ram(self):
        return self.__ram

    @ram.setter  # 인스턴스 변수 이름.setter
    def ram(self, ram):
        print(f"{self.__ram}의 (RAM)크기가 {ram}으로 변경.")
        self.__ram = ram

    @property
    def ssd(self):
        return self.__ssd

    @ssd.setter
    def ssd(self, ssd):
        print(f"{self.ssd}의 (SSD)크기가 {ssd}으로 변경.")
        self.__ssd = ssd

    def __del__(self):
        print(f"{self.name} 종료합니다")


if __name__ == "__main__":
    iMac = Computer('64G', '2T', '3T', 'i7', 'imac20', 'silver', 'desktop')

    iMac.ram = '128G'  # 얘가 호출을하는 것이다.
    print(f"iMac.ram getter: {iMac.ram}")

    iMac.ssd = '10T'
    print(f"iMac.ssd getter: {iMac.ssd}")
    
    
출력
64G의 (RAM)크기가 128G으로 변경.
iMac.ram getter: 128G
2T의 (SSD)크기가 10T으로 변경.
iMac.ssd getter: 10T
imac20 종료합니다

 

@property :  private에 바로 접근할 수 있는 데코레이션이다. 

@인스턴스 변수. setter : 초기화하는 값을 줘서 원하는 결과를 반환한다. iMac.ram = '128G' 코드는 setter에 있는 코드를 실행시킨다.

 

 

상속성

- 자식 클래스가 부모 클래스의 특성과 기능을 물려받는 것이다. 예를 들면 생물을 호흡을 한다. 동물과 식물은 호흡을 하지만 동물은 이동을 하고, 식물은 광합성을 한다. 동물에서도 조류는 호흡, 이동, 날개가 있다. 이처럼 상위 카테고리의 특징을 상속받는 걸 상속성이라 한다.

 

코드를 보자.

 

class person:
    def thinking(self):
        print("생각 중입니다")


class student(person):  # person 의 인스턴트를 상속받는 것
    def study(self):
        print("공부 중입니다.")


class porf(person):
    def lecture(self):
        print("강의 중입니다")


person_p = person()
student_s = student()
prof_p = porf()

print("1. person_p.thinking")
person_p.thinking()
print("2. student_s.thinking")
student_s.thinking()  # 상속받음
print("3. student_s.study()")
student_s.study()
print("4. porf_p.lecture")
prof_p.lecture()

출력
1. person_p.thinking
생각 중입니다
2. student_s.thinking
생각 중입니다
3. student_s.study()
공부 중입니다.
4. porf_p.lecture
강의 중입니다

 

상속은 간단하다. 클래스 명(상속받을 클래스명)으로 사용하면 된다. 학생에는 thinking이라는 메서드가 없지만 person을 상속받았기에 사용할 수 있는 것이다.

 

 

다형성

- 같은 메서드 이름으로 다른 동작을 하는 것. 자식에서 재정의를 하는 것. 재정의한 게 출력됩니다. 만약 상속을 받은 메서드 중에 "노래 듣기 = 신나는 노래"가 있었다고 예를 들어보자. 하지만 자식 클래스에서 "노래 듣기 = 발라드 노래"로 바꿨다면 "노래 듣기" 코드를 불러오면 "발라드 노래"가 출력된다. 

 

 

이처럼 객체지향 프로그래밍의 특징을 알아보았다.

 

 

반응형

댓글