python : :캡슐화 정의/ 상속의 정의/ super().__init__() 사용법

권수민·2023년 8월 31일
1

클라스 속성을 배우다보면, 상속하는 형태의 클라스들을 볼 수 있다.

상속 (inherit)

상속은 이미 정의된 클래스에서 속성과 메서드를 물려받아 새로운 클래스를 생성하는 것을 말합니다.
=> 메소드와 속성을 재사용 => 코드 중복을 줄이고 모듈성을 높인다.

# 기본 클래스 (부모 클래스)
class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        pass

# 파생 클래스 (자식 클래스)
class Dog(Animal):
    def speak(self):
        return f"{self.name} says Woof!"

### class Cat(Animal):
    def speak(self):
        return f"{self.name} says Meow!"

# 객체 생성 및 사용
dog = Dog("Buddy")
cat = Cat("Kitty")

print(dog.speak())  # 출력: Buddy says Woof!
print(cat.speak())  # 출력: Kitty says Meow!

Animal 이라는 클라스를 상속받아 그것의 속성인 name 과 메소드를 재사용한것.

super()

현재 클래스의 부모클래스를 참조 -> 일종의 프록시 객체를 반환합니다.

간단히 말해 프록시 객체:
동일한 데이터베이스 사용, 하지만 python 코드 상에서의 행동을 변경하고 싶을 때 사용 => 커스터마이징

여기서 프록시 객체 프록시 모델은 위의 설명과 같게:

기존모델과 동일한 데이터베이스를 사용하지만,
그 모델의 python레벨에서의 행동(메타,옵션,메서도,매니저 등의 python코드상에서의 행동)만을 수정하는것이라고 말할 수 있다.

사용사례:
1. 같은 데이터에서 다른 phython레벨에서의 동작이 필요하다던가
2. 기본 쿼리셋 변경이 필요할때 : (relatedmanager와 같은)모델 메니저를 사용하여 변경

예) 장고에서의 프록시 모델

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

class MyPerson(Person):
    class Meta:
        proxy = True

    def do_something(self):
        # 여기에 특정 동작을 정의
        pass

위의 Person모델과 같은 데이터베이스 테이블을 사용하지만, 추가적인 do_something 이라는 메서드를 가지고 있다.

프록시 모델을 사용하려면, Meta 클래스 내에서 proxy 옵션을 True로 설정해야 한다.

이렇게 프록시 모데를 사용할때는

프록시

프록시 패턴은 객체 지향 설계 패턴 중 하나로,

-제어목적(접근 제어, 호출),
-지연로딩(일부분 초기화, 필요한 시점에 전체객체 로딩),
-로그,보안및 검증(메서드 호출 로그를 기록, 보안검사 수행,입력검증 등),
-분산시스템(원격프록시 사용 -> 원격객체의 로컬 인터페이스를 제공)

다양한 목적으로 프록시를 사용하여 기능을 제어하거나 확장할 수 있도록 합니다.

따라서 super().init() 형태로 부 초모 클래스의기화 메서드를 호출할 수 있습니다.

class BaseClass:
    def __init__(self):
        print("BaseClass의 __init__ 메서드 호출")

class DerivedClass(BaseClass):
    def __init__(self):
        super().__init__()  # 여기서 BaseClass의 __init__ 메서드를 호출
        print("DerivedClass의 __init__ 메서드 호출")

obj = DerivedClass()


#출력값
BaseClass의 __init__ 메서드 호출
DerivedClass의 __init__ 메서드 호출

코드를 보면 DerivedClass().__init__함수안에 부모클라스인 BaseClass()의 메소드인 __init__()을 호출하고 그 다음것을 실행 print("DerivedClass의 init 메서드 호출") 해주고 있는것.

캡슐화 (Encapsulation)

객체지향 프로그래밍에서는 데이터와 그 데이터를 다루는 메서드들을 하나로 묶어 캡슐화합니다.

캡슐화된 객체는 외부에서 직접적으로 접근할 수 없으며, 메서드를 통해서만 데이터를 조작할 수 있습니다.

이를 통해 데이터의 보안성과 안정성을 높일 수 있습니다.

class Example:
    def __init__(self):
        self.__private_var = "I am private"

obj = Example()
# print(obj.__private_var)  # 이 코드는 오류를 발생시킵니다.

# 그러나 다음과 같이 이름 변경된 속성에 접근하는 것은 가능합니다.
print(obj._Example__private_var)  # "I am private"를 출력합니다.

캡슐화는 객체의 상태와 기능을 숨기고 (즉, 세부 구현을 숨기고) 공개 인터페이스만을 제공하는 개념입니다.

__ 접두사를 사용하여 변수나 메서드를 "비공개"로 설정하면 이름 변경(name mangling)이 발생하여 직접적인 접근이 어려워

=> __(더블언더스코어)접두사가 붙은 변수나 메소드는 이름 변경(name mangling)이 발생.
이 이름 변경의 결과로 실제 변수나 메서드 이름은
_클래스이름__변수명 또는
_클래스이름__메서드명 형태로 바뀝니다.

즉 위에 print(obj._Example__private_var)는 __priavate_var를 비공개 처리하면서 이름이 변경이 발생되어서=> _Example__private_var로 바뀌었기 때문에 접근이 가능해 프린트 되어진것이다.

profile
초보개발자

0개의 댓글