1월 30, 2022

TIL - Class

 객체지향 프로그래밍

: 시스템을 컴퓨터 명령어의 목록으로 구성하지 않고, 여러 다양한 객체들의 집합으로 구성하는 것.

= 프로그램을 객체(object)라는 기본 단위로 나누고, 객체들의 상호작용으로 기능을 구현하는 방식


클래스 없이 코딩을 하게 되면, 데이터함수가 따로 분리돼 정의되므로 문제가 생깁니다.

함수의 사용자가 함수의 작동 로직에 대해 이해도가 부족하다면, 어떠한 데이터와 필드를 넘겨줘야 하는지 이해하지 못했기에 함수를 사용하는데 있어 불편이 커지고 잘못된 매개변수를 넘길 수 있기에 오류의 가능성도 높아집니다. 


따라서 클래스를 사용합니다

Class의 정의: Class = Data + Functions


일단 클래스의 객체가 생성되고 나면, 그 후에는 함수의 코드가 어떻게 구현됐는지 몰라도 함수를 사용하는데 아무런 문제가 없습니다. 

더불어서, 클래스를 정의함으로써 새로운 type이 생기게 됩니다.

다시 말해, 클래스는 (자동차, 사용자와 같은) 어떠한 개념/컨셉/실체를 나타내는 데이터해당 데이터를 기반으로 실행시킬 수 있는 함수들을 분리하지 않고 하나로 묶어서 해당 개념을 표현하는 나만의 새로운 데이터 타입을 만들 수 있게 하여 프로그래밍을 훨씬 효과적으로 할 수 있도록 해줍니다.


Inheritance(상속): 

기존 클래스를 확장해서 코드를 재사용하기 위해 사용합니다

Encapsulation(캡슐화)

:캡슐 안의 내용물이 드러나지 않듯이, encapsulation은 안의 정보가 드러나지 않는 것을 말합니다

즉, 클래스가 담고 있는 데이터를 노출시키지 않는 것을 말합니다. 클래스가 담고 있는 데이터를 클래스 외부에서의 접근은 막고, 클래스 내부적으로만 접근을 허용하는 것.

예를 들어 car이라는 클래스를 만들었을때

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class Car:
    def __init__(self, maker, year, model, ai_auto_drive_mode, options):
        self.maker              = maker
        self.year               = year
        self.model              = model
        self.ai_auto_drive_mode = ai_auto_drive_mode

    def drive(self):
        if self.ai_auto_drive_mode:
            print("AI가 대신해서 운전하고 있습니다. 목적지에 도착할 때까지 편히 누워서 넷플릭스나 시청하시지요!")
        else:
            print("AI는 무슨! 얼른 운전대 안 잡니?")

    def print_info(self):
        print(f"{self.maker}, {self.model} {self.year}")

차의 maker와 year(생산연도) model이 바뀔 수 없겠죠?(현대차가 페라리로 변하진 않으니)

그러나 위의 코드에서는 아직 이러한 일이 가능합니다

1
2
3
4
5
6
7
car.maker = "HYUNDAI"
car.year  = 2050

car.print_info() 
# => "HYUNDAI, E-Class 2050"

이런말도 안되는 자동차가 코드상으로는 현재 나올  있다.


현재 Car 클래스가 언제든지 데이터들을 바꿀 수 있는 구조로 구현돼 있기 때문이죠


문제점 : 클래스를 직접 구현한 사람이 아니라면, 클래스의 작동 원리나 데이터의 정확한 목적에 대해 오해할 수 있으므로 잘못된 데이터를 설정할 수 있음

해결책: 이러한 부적절 사용을 방지하기 위해 클래스 데이터 중 직접 노출을 제한해야 하는 데이터들은 encapsulation을 통해서 접근을 아예 막거나 제한적 접근만 허용

encapsulation을 통해 Car class의 문제점을 해결해보겠습니다 


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class Car:
    def __init__(self, maker, year, model, ai_auto_drive_mode): 
        self._maker              = maker #각
        self._year               = year  #데이터를의 값 저장하는 변수들 이름에
        self._model              = model # _ (밑줄) 이 붙어있음
        self._ai_auto_drive_mode = ai_auto_drive_mode # ㅇㅇㅇ
# 변수나 함수 이름앞에 _밑줄을 붙였다는 의미는 해당변수는 private이란 것

    def drive(self):
        if self.ai_auto_drive_mode:
            print("AI가 대신해서 운전하고 있습니다. 목적지에 도착할 때까지 편히 누워서 넷플릭스나 시청하시지요!")
        else:
            print("AI는 무슨! 얼른 운전대 안 잡니?")

    def print_info(self):
        print(f"{self.maker}, {self.model} {self.year}")

    def get_ai_auto_drive_mode(self):   #getter함수로 값을 읽어들이고
        return self._ai_auto_drive_mode

    def set_ai_auto_drive_mode(self, value):  #setter함수로 값을 지정하게함
        # 2020년 전에는 AI 자동 주행이 없었으므로 구식 모델은 탑재 불가능
        if self._year >= 2020:
            self._ai_auto_drive_mode = value
        else:
            print("2020년 전에는 AI 자동 주행이 없었으므로 무조건 False값만 가능합니다")
            self._ai_auto_drive_mode = False

    def get_maker(self): #getter 함수만 정의하고 setter함수는 누락시켜서 변경불가하게 구현
        return self._maker

    def get_year(self): #getter 함수만 정의하고 setter함수는 누락시켜서 변경불가하게 구현
return self._year def get_model(self): #getter 함수만 정의하고 setter함수는 누락시켜서 변경불가하게 구현
return self._model maker = property(get_maker, None) year = property(get_year, None) model = property(get_model, None) ai_auto_drive_mode = property(get_ai_auto_drive_mode, set_ai_auto_drive_mode)


car.maker = "Hyundai"
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-12-fd95d6e0e115> in <module>
----> 1 car.maker = "Hyundai"

AttributeError: can't set attribute

=> 변경이 불가하다 (cant' set!!!)


car.ai_auto_drive_mode = True
2020 전에는 AI 자동 주행이 없었으므로 무조건 False값만 가능합니다
setter함수 참조, year값이 2019일때.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
car = Car(
   ...:     maker              = "BENZ",
   ...:     year               = 2019,
   ...:     model              = "E-Class",
   ...:     ai_auto_drive_mode = False

car.maker = "Hyundai"
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-12-fd95d6e0e115> in <module>
----> 1 car.maker = "Hyundai"

AttributeError: can't set attribute  # 변경이 불가능함!

car.ai_auto_drive_mode = True
2020 전에는 AI 자동 주행이 없었으므로 무조건 False값만 가능합니다


이제 __가 붙은 private 변수는 변경이 불가능해지고, 값을 지정할 때도 setter함수에 따라 지정되는 것을 볼 수 있습니다.

Polimorphism(다형성)

:프로그램 언어의 각 요소들이 다양한 자료형에 속하는 것이 허가되는 성질/ 반대말은 단형성

=> Child class(B)가 Parent class(A)를 상속받으면 Polimorphism 관계를 가집니다.

이런 경우에 부모 클래스를 기대하는 곳에 자식 class를 집어넣을 수 있습니다(B is A)

이는 A가 가지고 있는 것을 B(자식)이 전부 가지고 있기에 가능한 것입니다.