'''
# CLASS

클래스는 함수처럼 반복적인 소스코드를 최소화시키는 프로그래밍 기술이다.
클래스를 만들 때는 해당 클래스의 객체가 어떤 방식으로 동작할 것인지를 생각하고 만드는 것이 좋다.
클래스로 정의된 객체는 프로그램 상에서 인스턴스라는 변수로 사용될 수 있다.

클래스는 멤버와 메소드로 이루어진다.
- 멤버: 클래스 내부에 포함되는 변수
- 메소드: 클래스 내부에 포함된 함수
즉, 클래스는 변수와 함수로 이루어진다는 것이다.
클래스는 하나의 주제를 공유하는 함수를 모아놓은 것이라고 생각하면 편하다.
'''

'''
 1. 클래스 생성자:
- 클래스의 생성자는 함수형태(def)로 존재하며, 해당 함수는 __init__이라는 이름을 가진다.
  즉, 클래스를 이용하여 인스턴스를 만들기 위해서는 init 함수(생성자)가 사용된다.
- init함수는 매개변수로 self라는 것을 기본적으로 가지고 있는다.
- self 뒤에 추가하는 매개변수는 해당 클래스의 멤버가 될 수 있다.

2. 클래스 맴버:
- 'self.매개변수'로 클래스의 멤버를 하나씩 설정해준다.
   즉, 클래스 생성자의 매개변수로 들어온 값을 클래스의 인스턴스의 멤버변수로 설정하겠다고 하는 것이다.
   예를 들어 매개변수'flavor'로 들어온 값을 'self.flavor'라는 멤버변수에 할당해준다
- self.매개변수는 해당 클래스내에서 호출할 수 있다. 
- 함수에서 'self.매개변수'를 호출하면 클래스를 사용할 때 입력한 매개변수가 
  각각 해당 'self.매개변수'에 할당되어 처리된다.

3. 클래스 메소드
모든 클래스의 함수는 기본적으로 self라는 매개변수를 첫 번째 매개변수로 갖는다.

4. Setter 함수
- Setter 함수는 일반적으로 'set_매개변수'꼴의 이름을 가진다. set_flavor의 경우 flavor를 바꾸는 setter 메소드이다.
- Setter 함수를 통해 해당 클래스로 만들어진 인스턴스가 가지고 있는 변수 값을 변경하고 싶을 때 사용된다.
  즉, Setter 함수의 매개변수로 들어온 값으로 인스턴스의 변수값을 바꿀 수 있다.
- Setter 함수의 매개변수로는 변경하고자 하는 인스턴트의 변수값이 들어간다.

5. 소멸자
- 소멸자는 쓸모를 다한 인스턴스를 내부적으로 소멸시키는 함수이다.
- 소멸자는 del 키워드로 작성하면 된다.
  소멸자 실행 후 따로 설정을 하지 않으면 아무런 공지 없이 소리소문 없이 인스턴스가 사라진다.
  그러면 답답하니까 실행됐으면 print("없어졌다")정도 출력하도록 하면 마음에 안정이 찾아온다.
- 파이썬은 객체지향프로그램이라 하나의 변수를 만들면 
  내부적으로 메모리상에 해당 변수에 대해 동적으로 메모리 공간을 할당한다.
  즉, 메모리 상에 데이터가 할당되는 것이다.
  그렇기 때문에 할당된 데이터가 많으면 프로그램이 힘들어하기 때문에 
  더이상 필요하지 않은 변수/객체는 메모리 상에서 할당을 해제해주는 것이 좋다.
'''

class Ice_Cream:  # Ice Cream에 대한 class를 한번 정의해보자.
    def __init__(self, flavor, company): # 1. 클래스 생성자.
        self.flavor = flavor # 2. 클래스 멤버
        self.company = company # 2. 클래스 멤버
    def __del__(self): # 5. 소멸자
        print("해당 인스턴스 할당 해제")
    def show_info(self): # 3. 클래스 메소드
        print("이것은", self.company,"의", self.flavor,"맛 아이스크림이다.")
    def set_flavor(self, flavor): # 4. Setter 함수
        self.flavor = flavor

# 이렇게 하나의 클래스가 정의될 수 있다.
# 위 클래스 해석: Ice_Cream이라는 인스턴스는 flavor과 company라는 속성을 가지며,
#                 show_info라는 함수로 해당 임스턴스의 정보를 출력할 수 있다.

'''
인스턴스 생성
'''
# 이제 인스턴스를 생성해보자.
ice_cream1 = Ice_Cream("민트초코", "베스킨라빈스") # flavor은 민트초코, company는 베스킨라빈스인 Ice_Cream인스턴스를 만들었다.
ice_cream1.show_info() # 인스턴스에 show_info함수를 수행한다.

# 인스턴스의 멤버변수에는 '인스턴스.매개변수'를 통해 접근할 수 있다.(가운데 온점(.)이다.)
print(ice_cream1.flavor,"맛있다") # ice_cream1인스턴스에 있는 flavor만 추출.
print(ice_cream1.company,"일 잘하네") # ice_cream1인스턴스에 있는 company만 추출.

'''
Setter 함수 사용하기
'''
# 위에서 작성한 Setter 함수는 '인스턴스 이름.Setter 함수 이름(변수 변경 결과)

ice_cream1.set_flavor("바람과 함께 사라지다")
print(ice_cream1.flavor,"도 먹을래")

'''
소멸자 사용하기
'''
# 인스턴스 할당이 해제된 이후에 해당 변수에 접근하려고 하면 에러가 뜬다. 접근이 안된다.
# 없어졌으니까.
del ice_cream1