캡슐화
- 객체의 일부 구현 내용을 외부 접근으로부터 막기 위함
- 객체의 속성과 행동을 하나로 묶기 위함
class Citizen:
"""주민 클래스"""
drinking_age = 19
def __init__(self, name, age, resident_id):
"""이름, 나이, 주민등록번호"""
self.name = name
self.age = age
self.resident_id = resident_id
def authenticate(self, id_field):
"""본인이 맞는지 확인하는 메소드"""
return self.resident_id == id_field
def able_to_drink(self):
"""음주 가능 나이인지 확인하는 메소드"""
return self.age >= Citizen.drinking_age
def __str__(self):
"""주민 정보를 문자열로 리턴하는 메소드"""
return f"{self.name}님은 {str(self.age)}살입니다."
taki = Citizen("타키탸키", 26, "123456")
fire = Citizen("파이리", 12, "654321")
위의 클래스는 주민을 나타내기 위한 클래스이다. Citizen 클래스는 주민 이름과 나이 주민번호를 인스턴스 변수로 가진다.
메소드로는 주민번호를 이용해서 본인 인증을 하는 authenticate 메소드와 음주가 가능한 나이인지 알려주는 able_to_drink 메소드, 그리고 주민 정보를 문자열로 리턴하는 던더 str 메소드를 가지고 있다. 그런데 이 프로그램에는 몇 가지 문제점이 있다.
print(taki.resident_id)
taki.age = -26
주민의 resident_id를 출력하면 주민번호가 유출될 수 있고 age 변수의 값을 마음대로 지정할 수 있기 때문에 음수 값이 들어갈 수도 있다. 나이 값을 마음대로 정할 수 있다는 것은 또 다른 문제가 있다. 이 프로그램에는 음주가 가능한 나이인지를 확인하는 메소드가 있는데 12살 파이리 어린이의 나이를 바꾸면 음주 가능 나이로 판별이 된다.
이러한 문제를 해결하려면 Citizen 클래스에 캡슐화를 적용해야 한다. 캡슐화에는 두 가지 정의가 있다.
1. 객체의 일부 구현 내용에 대한 외부로부터 직접적인 액세스를 차단하는 것
2. 객체의 속성과그것을 사용하는 행동을 하나로 묶는 것
객체 내부 숨기기
클래스 외부에서 어떤 변수가 메소드에 직접 접근하는 것을 막는다. 숨기고자 하는 변수 이름 앞에 언더바 두개를 붙이면 된다.
class Citizen:
"""주민 클래스"""
drinking_age = 19
def __init__(self, name, age, resident_id):
"""이름, 나이, 주민등록번호"""
self.name = name
self.__age = age
self.__resident_id = resident_id
def authenticate(self, id_field):
"""본인이 맞는지 확인하는 메소드"""
return self.__resident_id == id_field
def able_to_drink(self):
"""음주 가능 나이인지 확인하는 메소드"""
return self.__age >= Citizen.drinking_age
def __str__(self):
"""주민 정보를 문자열로 리턴하는 메소드"""
return f"{self.name}님은 {str(self.__age)}살입니다."
taki의 주민번호를 출력해보자.
print(taki.__resident_id)
다음과 같은 에러 메세지가 나온다. 이 에러 메세지는 taki 인스턴스에는 __resident_id라는 변수가 없다고 나온다.
AttributeError: 'Citizen' object has no attribute '__resident_id'
이번에는 메소드 앞에 언더바 두 개를 붙여보자.
def __authenticate(self, id_field):
"""본인이 맞는지 확인하는 메소드"""
return self.__resident_id == id_field
__authenticate 메소드를 호출하면
taki.__authenticate("123456")
같은 에러 메세지가 뜬다. 이 말은 곧, __authenticate 메소드를 클래스 밖에서 호출할 수 없단느 것이다.
메소드를 통해 변수에 접근하기
이제 캡슐화가 적용된 __resident_id와 __age는 클래스 외부에서 값을 읽을 수도, 설정할 수도 없다. 문제는 만약 주민의 나이를 변경하고 싶어도 __age에 접근할 수가 없기 때문에 수정이 불가능하다는 것이다. 이와 같은 상황을 해결하기 위해서는 변수에 접근할 수 있는 메소드를 따로 만들어야 한다.
def get_age(self):
return self.__age
이렇게 하면 Citizen 클래스 밖에서도 __age의 값을 읽을 수 있다. 이런 식으로 숨겨진 변수에 접근 가능한 메소드가 있으면 클래스 밖에서도 해당 변수에 바로 접근할 수 있다.
def set_age(self, value):
self.__age = value
이렇게 하면 이제 __age 변수는 클래스 밖에서 읽을 수도 있고 설정할 수도 있다.
print(taki.get_age())
taki.set_age(12)
print(taki.get_age())
26
12
정리하자면, Citizen 클래스의 __age 변수는 캡슐화가 적용되었기 때문에 외부에서 바로 접근할 수는 없다. 하지만 해당 변수를 활용하는 메소드를 정의하면 접근이 가능하다.
이렇게 접근할 수 있는 메소드를 만드는 것이 바로 캡슐화의 두 번째 정의에 해당된다. 두 번째 정의에서 '하나로 묶는 것'이라는 표현이 있었는데 이 말은 '변수에 접근하는 통로를 메서드로 제한한다'는 것을 의미합니다.
'Python' 카테고리의 다른 글
멀티 프로세스 vs 멀티 스레드 (0) | 2022.05.18 |
---|---|
[Python] 타입 어노테이션/힌트 (0) | 2022.04.11 |
[Python] 추상 클래스 사용하기 (@abstractmethod) (0) | 2022.04.07 |
[Python] 데코레이터 사용하기 (0) | 2022.04.07 |
[Python] 프로퍼티 (Property) 사용하기 (2/2) (0) | 2022.04.07 |
댓글