본문 바로가기

코딩/Python

[Python/파이썬] Class(클래스) 기초 정리 - 2 : has-a 관계, 상속 개념

반응형

 

※ 이 글을 쓰는 사람은 SW 비전공자입니다.

※ 개인 공부를 위해 정리하는 글이며, 작성한 코드들은 효율성, 깔끔함(?) 등과는 거리가 멀 수 있습니다.

 

2021.03.14 - [코딩/Python] - [Python/파이썬] Class(클래스) 기초 정리 - 1 : 개념, 사용법

2021.03.20 - [코딩/Python] - [Python/파이썬] Class(클래스) 기초 정리 - 2 : has-a 관계, 상속 개념

2021.03.21 - [코딩/Python] - [Python/파이썬] Class(클래스) 기초 정리 - 3 : 다중상속, super().__init__(), 메서드 오버라이딩

2021.03.22 - [코딩/Python] - [Python/파이썬] Class(클래스) 기초 정리 - 4 : 추상 클래스, 클래스 변수

2021.03.27 - [코딩/Python] - [Python/파이썬] Class(클래스) 메서드 self 설명


1. 인스턴스 변수

 

1) 인스턴스 vs 객체

 

  C++이든 파이썬이든 객체 지향 프로그래밍을 지원하는 언어라면 인스턴스객체라는 단어를 많이 쓴다. 어떤 코드를 설명하는 글을 읽을 때 이 2개를 혼용해서 쓰는 경우가 많아 굉장히 헷갈린다. (사실 아직 이해가 정확히 안감..)

 

  이전 포스팅에서 클래스를 무기로 클래스에 비유해서 설명해봤는데 이번에도 같은 코드로 설명해보겠다. 객체와 인스턴스의 차이는 위키 독스-'점프 투 파이썬'에서 잘 설명하여 참고하여 정리했다.

 

# 무기 클래스 정의 
class Weapone(): 
pass

#'무기' 클래스 객체 '칼'을 생성해보기" 
sword = Weapone()

 

 -. sword는 객체이다.

   -. sword 객체는 Weapone 클래스의 인스턴스이 다.

      : 인스턴스는 어떤 클래스의 객체인지 관계를 설명할 때 사용하는 용어라고 한다.

   -. 객체랑 인스턴스 모두 비슷한 경우에 사용하여 헷갈리므로 위와 같이 정리

 

 

2) 인스턴스 변수

  각 인스턴스들은 같은 클래스로 선언하여도 다른 변수를 가질 수 있다. 아래와 같은 코드를 생각해보자. 결과를 보면 알겠지만 같은 클래스여도 다른 변수를 가질 수 있다. 동일한 변수여도 다른 값을 가질 수 있다.

 

#무기 클래스를 선언. 내부 내용은 아무 것도 없음(pass)
class Weapone:
    pass

#sword 객체 선언
sword = Weapone()
sword.power = 10
sword.level = 5

#gun 객체 선언
gun = Weapone()
gun.power = 20
gun.type = "원거리"

#같은 class이지만 각각 다른 변수를 가질 수 있다.
print("칼의 공격력 : ",sword.power)
print("칼의 레벨제한 : ",sword.level)
print("총의 공격력 : ",gun.power)
print("총의 공격타입 : ",gun.type)

 

<결과>

 

칼의 공격력 :  10
칼의 레벨제한 :  5
총의 공격력 :  20
총의 공격타입 :  원거리

Process finished with exit code 0

 

 

 

2. has -  a 관계 (객체 속의 객체)

 

  has - a 관계는 객체가 다른 객체를 포함한다는 말이다.  쉽게 설명하기 위해 이전에 설명했던 게임을 비유로 해보겠다.

RPG 게임에는 소지품을 보관할 수 있는 인벤토리(혹은 가방, 창고) 개념이 있다. 이 인벤토리도 생각해보면 또 다른 클래스 개념으로 생각할 수 있다. 인벤토리는 보관 최대 개수, 공간 등의 속성을 가진다.

 

  무기 클래스의 칼과 총(객체)는 이 게임 유저의 인벤토리(객체)에 들어갈 수 있다. 이런 관계를 has - a 관계라고 한다.

어려우니까 다시 도식화를 쉽게 해보았다.

 

< has -a 관계 도식화 >

 

  위 도식화에 맞게 코드를 짜보았다. 인벤토리에 대한 클래스를 선언하고 __int__에서 기본 인벤토리에 대한 속성 값을 정의하였다. 그리고 인벤토리를 열고 닫는 메서드, 아이템을 넣는 메서드를 정의하였다.

(아래 코드는 위키 독스 - '왕초보를 위한 python'을 참고함. 참고 링크는 본문 하단에 기재.)

 

class Inventory:
    #인벤토리 기본속성 : 닫혀있다. 빈공간이다.(리스트로 선언)
    def __init__(self):
        self.opend = False
        self.item_space = []
    
    #인벤토리 열기 메소드 : 열려있는 상태로 변경한다.
    def open(self):
        self.opened = True
        print("인벤토리가 열렸습니다. 아이템을 넣을 수 있습니다.")

	#인벤토리에 아이템 넣기 메소드 : 기본 속성인 item_space에 아이템을 추가한다.
    def put(self, something):
        if self.opened == True:
            self.item_space.append(something)
            print('아이템을 인벤토리에 넣었습니다.')
        else:
            print("인벤토리를 먼저 열어주세요")
            
	#인벤토리 닫기 메소드 : 닫혀있는 상태로 변경한다.
    def close(self):
        self.opend= False
        print("인벤토리를 닫았습니다.")

class Weapone:
    pass

sword = Weapone()
item_bag = Inventory()
#아이템 인벤토리를 연다.
item_bag.open()

#칼을 인벤토리에 넣어보자.
item_bag.put(sword)

#item_space 에 접근하여 뭐가 있는지 확인해보자.
print("인벤토리에 보유중인 아이템 : ",item_bag.item_space)

#인벤토리를 닫자
item_bag.close()

 

<결과>

인벤토리가 열렸습니다. 아이템을 넣을 수 있습니다.
아이템을 인벤토리에 넣었습니다.
인벤토리에 보유중인 아이템 :  [<__main__.Weapone object at 0x000001FC6533D288>]
인벤토리를 닫았습니다.

Process finished with exit code 0

 

  결과를 보면 알겠지만 'Inventory' 클래스의 item_bag 객체 안에 'Weapone' 클래스의 객체가 들어간 것으로 확인된다.

(item_space는 리스트 타입)

 

 

3. 상속(Inheritance)

  

  상속은 어떠한 클래스가 다른 클래스의 메서드, 속성을 물려받을 수 있는 것을 말한다. 물려받는다의 이름처럼 부모, 자식 간의 관계라고 생각하여 물려주는 클래스는 '부모 클래스', 물려받는 클래스는 '자식 클래스(=하위 클래스)'라고 한다.

 

  다시 게임 아이템 무기 클래스로 돌아가 보자. 무기 클래스는 공통적으로 어떤 타입인지?, 어떤 종류의 무기인지라는 속성을 가지고 있다. 무기 중 Sword(검)은 무기 클래스에 속하는 또 다른 클래스로 정의할 수 있다.

(왜냐면 검은 무기의 특성을 그대로 가지고 있으니까)

 

  클래스 상속 선언은 아래와 같다.  아래 예시 코드를 보면 쉽게 이해할 수 있다.   

 

* Class 상속 사용법

Class 'Class명'('상속받을 Class') :

# 무기 클래스 선언
class Weapone:
    def __init__(self, type, name):
        self.type = type
        self.name = name
        print("저는 무기 클래스입니다! 공격할 수 있습니다!!")
    
    #무기의 종류를 출력하는 메소드
    def what_weapone(self):
        print("어떤 타입이야? :", self.type)
        print("어떤 무기야? : ", self.name)

#Sword라는 클래스를 선언하고 Weapone 클래스를 상속한다.
class Sword(Weapone):
    pass

#Sword 클래스 객체 선언
short_sword = Sword("근거리", "단검")

#부모 클래스의 메소드인 what_weapone() 호출
short_sword.what_weapone()

 

<결과>

 

저는 무기 클래스입니다! 공격할 수 있습니다
어떤 타입이야? : 근거리
어떤 무기야? :  단검

Process finished with exit code 0

 

  코드를 보면 Sword라는 클래스에는 속성이나 메서드 등 어떤 것도 정의되어있지 않지만 Weapone 클래스를 상속함으로써 Weapone 클래스의 메서드를 그대로 호출할 수 있다.

 

   그럼 왜 상속을 해야 하는가는 아래 2가지로 정리해보았다.

이유1 :  기존 클래스를 그대로 유지하기 위해
  기존 클래스를 그대로 유지하고 기능을 추가하거나 기존 기능을 변경하려 할 때 사용한다.

이유2 : 코드 관리의 편의성을 위해
  클래스별로 각각 메소드와 속성을 작성해놓으면 공통적인 내용 수정이 필요할 때 클래스마다 각각 수정해야 한다. 공통적인 부분에 대해 하나의 클래스로 정의하고 상속하는 방식으로 관리하면 수정이 편해진다. 

 

 

 다음 포스팅은 다중 상속, 메서드 오버 라이딩 등의 개념에 대해서 정리해보려고 한다.

 


참고자료 1 : 아무튼 워라벨 hleecaster.com/python-class/

참고자료 2 : 위키 독스 - '점프 투 파이썬'  wikidocs.net/28

참고자료 3 : 위키 독스 - '왕초보를 위한 파이썬'  wikidocs.net/8

728x90