오늘은 클래스를 더 크게 보는 방법을 배웠다
중급 1일차와 2일차에서는 클래스를 만들고, 객체를 생성하고, __init__으로 초기 상태를 넣는 흐름을 배웠다. 그때까지는 클래스 하나를 독립적으로 만드는 느낌이 강했다. 그런데 오늘 배운 상속은 클래스끼리 관계를 맺는 방식이었다.
즉, 이제부터는 “클래스를 어떻게 하나 만들까”가 아니라, “이미 있는 클래스를 바탕으로 어떻게 더 좋은 클래스를 만들까”를 생각하게 된다.
처음엔 상속이 어려워 보였지만, 실제 예제는 꽤 단순했다. 이미 잘 만들어진 계산기 클래스를 두고, 새 기능 하나를 추가하는 흐름이었다. 이 구조를 이해하고 나니 상속은 복잡한 문법이라기보다, 기존 코드를 버리지 않고 확장하는 실용적인 방법에 가까웠다.
1. 기본 클래스는 사칙연산 계산기였다
class FourCal:
def __init__(self, fir, sec):
self.first = fir
self.second = sec
def add(self):
return self.first + self.second
def sub(self):
return self.first - self.second
def mul(self):
return self.first * self.second
def div(self):
return self.first / self.second
이 클래스는 아주 전형적인 객체지향 예제다.
- 생성자
__init__에서 두 수를 저장하고 - 메서드
add,sub,mul,div가 그 값을 이용해 동작한다
중급 2일차 관점에서 다시 보면, 이 클래스는 이미 꽤 잘 정리된 구조다. 객체가 만들어질 때 필요한 값이 들어가고, 메서드는 그 값을 활용해 기능을 수행한다.
즉, 상속은 아무 클래스에서나 갑자기 쓰는 개념이 아니라, 이렇게 기본 구조가 잡힌 클래스를 바탕으로 출발하는 것이다.
2. 상속은 기존 클래스를 바탕으로 새 클래스를 만든다
상속은 아래처럼 표현한다.
class MoreFourCal(FourCal):
def pow(self):
return self.first ** self.second
이 코드에서 MoreFourCal은 새 클래스이고, 괄호 안의 FourCal은 부모 클래스다.
즉, 이 한 줄은 이렇게 읽으면 된다.
“MoreFourCal은 FourCal의 기능을 이어받는 클래스다.”
처음에는 괄호 안에 왜 클래스 이름이 들어가는지 낯설 수 있다. 하지만 의미만 잡으면 간단하다. 어떤 클래스를 기반으로 새 클래스를 만들겠다는 선언이다.
3. 자식 클래스는 부모의 메서드를 그대로 쓸 수 있다
상속의 가장 중요한 장점은 부모 클래스의 기능을 다시 작성하지 않아도 된다는 점이다.
예를 들어 MoreFourCal에는 실제로 pow() 하나만 새로 정의되어 있다. 그런데도 아래 코드는 모두 동작한다.
mymore1 = MoreFourCal(4, 3)
print(mymore1.add())
print(mymore1.sub())
print(mymore1.mul())
print(mymore1.div())
print(mymore1.pow())
왜냐하면 add, sub, mul, div는 부모 클래스 FourCal에 이미 있기 때문이다.
즉, 자식 클래스는:
- 부모가 가지고 있던 기능을 물려받고
- 자신만의 기능을 새로 추가할 수 있다
이게 상속의 핵심이다.
처음 상속을 볼 때는 “새 클래스를 만들었는데 왜 부모 메서드가 같이 보이지?”라는 생각이 들 수 있다. 하지만 바로 그 점이 상속의 목적이다. 새 클래스를 만들면서도 기존 기능을 잃지 않는다.
4. 상속은 복붙 대신 재사용을 선택하는 방법이다
오늘 내용을 이해할 때 가장 중요한 문장은 이거였다.
“상속은 복사해서 다시 만드는 방식이 아니라, 이미 있는 구조를 재사용하는 방식이다.”
만약 상속 없이 같은 기능을 만들려면, 새 클래스 안에 아래 메서드들을 전부 다시 적어야 한다.
__init__add()sub()mul()div()
그리고 거기에 pow()까지 추가해야 한다.
이 방식은 두 가지 문제가 있다.
- 코드가 길어진다.
- 나중에 수정할 때 중복된 코드들을 함께 고쳐야 한다.
반면 상속을 쓰면 공통 기능은 부모에 두고, 새로 필요한 기능만 자식에 적으면 된다. 그래서 코드가 더 짧고, 구조도 더 분명해진다.
기초에서 함수를 써서 반복을 줄였다면, 중급에서는 상속으로 클래스 단위의 반복을 줄인다고 이해하면 좋다.
5. 생성자도 상속된다는 점이 중요했다
중급 2일차에서 __init__ 생성자를 배웠기 때문에, 오늘 상속을 보면서 더 분명해진 부분이 있다.
MoreFourCal 클래스에는 __init__이 따로 정의되어 있지 않다. 그런데도:
mymore1 = MoreFourCal(4, 3)
처럼 객체를 만들 수 있다.
이유는 부모 클래스 FourCal의 __init__을 그대로 물려받기 때문이다.
즉, 자식 클래스가 생성자를 따로 만들지 않아도 부모 클래스의 초기화 방식을 그대로 사용할 수 있다.
이 감각은 꽤 중요하다. 상속은 단순히 메서드 몇 개만 가져오는 게 아니라, 부모 클래스가 가진 기본 구조 전체를 이어받는다는 뜻이기 때문이다.
그래서 day2의 __init__ 이해가 day3에서 바로 연결된다.
- 부모 클래스는 초기 상태를 만드는 틀이고
- 자식 클래스는 그 틀을 유지한 채 기능을 더하는 존재다
이렇게 연결해서 보면 상속도 훨씬 덜 막연하게 느껴진다.
6. 부모 클래스와 자식 클래스는 역할을 나눠 생각하면 쉽다
상속 개념이 처음 어렵게 느껴지는 이유는 부모와 자식이라는 표현이 추상적으로 들리기 때문이다. 그래서 역할로 바꿔 이해하는 편이 더 쉽다.
부모 클래스
- 공통 기능을 가진 기본 클래스
- 여러 클래스가 함께 써야 하는 구조를 담는 곳
자식 클래스
- 부모 기능을 물려받는 클래스
- 필요한 기능만 추가하거나 바꾸는 곳
FourCal과 MoreFourCal을 이 관점으로 보면 아주 명확하다.
FourCal은 사칙연산이라는 기본 기능을 가진 부모 클래스MoreFourCal은 거듭제곱을 추가한 자식 클래스
즉, 공통 기능은 부모에, 확장 기능은 자식에 둔 것이다.
이 구조가 상속을 이해하는 가장 기본적인 틀이다.
7. 상속은 “비슷하지만 조금 다른 클래스”가 있을 때 특히 유용하다
오늘 예제가 계산기라서 단순해 보이지만, 실제로는 상속이 필요한 상황이 꽤 많다.
예를 들면:
- 기본 자동차 클래스가 있고, 전기차 클래스가 충전 기능을 추가하는 경우
- 기본 회원 클래스가 있고, 관리자 클래스가 권한 기능을 추가하는 경우
- 기본 계산기 클래스가 있고, 공학용 계산기 클래스가 추가 연산을 넣는 경우
이런 상황에서는 완전히 새 클래스를 처음부터 다시 만드는 것보다, 공통 부분은 부모에 두고 차이만 자식에 추가하는 편이 훨씬 자연스럽다.
즉, 상속은 “완전히 다른 대상”보다 “기본 구조는 같고 일부 기능만 늘어나는 대상”에 잘 어울린다.
8. 상속을 배우면 클래스 설계 방식이 달라진다
오늘 공부하면서 느낀 건, 상속은 단순히 문법을 하나 배우는 게 아니라 클래스를 나누는 기준을 바꾸는 개념이라는 점이다.
예전에는 그냥 기능이 필요하면 새 클래스 안에 모두 적는 식으로 생각하기 쉽다. 하지만 상속을 배우면 질문이 달라진다.
- 이 기능은 모든 클래스에 공통인가?
- 아니면 특정 클래스에만 추가되는 기능인가?
- 공통 부분은 부모로 올리고, 차이만 자식으로 뺄 수 있는가?
이런 질문을 하게 되면 코드가 훨씬 정리된다.
즉, 상속은 “문법 지식”이면서 동시에 “구조를 나누는 사고방식”이다.
9. 오늘 단계에서는 기능 추가까지 이해하면 충분하다
상속에는 나중에 더 어려운 개념도 많이 나온다.
- 메서드 오버라이딩
- 부모 메서드 호출
- 다중 상속
- 다형성
하지만 오늘 단계에서 가장 먼저 잡아야 할 감각은 그것보다 앞선 기본이다.
- 부모 클래스가 있다.
- 자식 클래스가 그 기능을 물려받는다.
- 자식 클래스는 필요한 기능을 추가할 수 있다.
이 세 줄만 분명하면 오늘 내용은 충분히 이해한 것이다.
즉, day3은 상속 전체를 끝내는 날이 아니라, “기존 클래스를 기반으로 새 클래스를 확장할 수 있다”는 감각을 잡는 날이라고 보는 편이 맞다.
10. 오늘 헷갈리기 쉬운 포인트
상속을 처음 배울 때 특히 헷갈릴 수 있는 부분은 아래와 같다.
class MoreFourCal(FourCal): 문법
괄호 안은 함수 매개변수가 아니라, 어떤 클래스를 상속받는지 표시하는 부분이다.
자식 클래스에 없는 메서드 호출
MoreFourCal에 add()가 직접 적혀 있지 않아도, 부모 클래스에서 물려받았기 때문에 사용할 수 있다.
생성자도 이어받는다는 점
자식 클래스에 __init__이 없어도 부모의 __init__이 적용될 수 있다. 이 부분이 이해되면 객체 생성 흐름이 한층 더 명확해진다.
즉, 상속은 “일부 기능만 복사”가 아니라 “부모 구조 전체를 기반으로 확장”하는 개념으로 보는 편이 정확하다.
11. 오늘의 실수 포인트
오늘 내용에서 놓치기 쉬운 부분은 아래와 같다.
- 상속은 클래스를 복붙하는 개념이 아니다.
- 자식 클래스는 부모 클래스의 속성과 메서드를 이어받을 수 있다.
- 자식 클래스는 부모 기능을 유지한 채 새 메서드를 추가할 수 있다.
- 생성자를 다시 쓰지 않아도 부모 생성자를 그대로 사용할 수 있는 경우가 있다.
- 상속은 공통 기능과 추가 기능을 분리하는 설계 방식과 연결된다.
즉, 상속을 배울 때는 문법보다 “왜 굳이 이렇게 구조를 나누는가”를 같이 생각해야 한다.
12. day2와 이어서 보면 흐름이 더 자연스럽다
중급 2일차에서는 객체를 만들 때 필요한 값을 __init__으로 받는 구조를 배웠다. 오늘은 그 구조를 가진 클래스를 그대로 기반으로 삼아, 더 큰 클래스를 만드는 흐름을 배웠다.
즉, 흐름은 이렇게 이어진다.
- day1: 클래스와 객체, 속성과 메서드의 기본 구조를 본다
- day2:
__init__으로 객체 초기화를 정리한다 - day3: 그렇게 만들어진 클래스를 상속으로 확장한다
이렇게 보면 중급 3일차는 갑자기 튀어나온 새 문법이 아니다. 앞에서 만든 클래스를 더 유연하게 재사용하는 단계다.
그래서 오늘은 클래스 공부가 한 단계 더 넓어졌다고 느껴졌다. 이제 클래스는 혼자 있는 대상이 아니라, 다른 클래스의 기반이 될 수도 있는 구조가 된다.
복습용으로 남기는 질문
이 글만 읽고 아래 질문에 답할 수 있으면 중급 3일차 내용은 잘 정리된 것이다.
1. 상속은 왜 사용하는가?
기존 클래스의 공통 기능을 재사용하면서, 필요한 기능만 추가하거나 바꾸기 위해 사용한다. 이렇게 하면 중복 코드가 줄고 구조가 더 깔끔해진다.
2. 부모 클래스와 자식 클래스는 각각 어떤 역할을 하는가?
부모 클래스는 공통 기능을 담는 기본 클래스이고, 자식 클래스는 그 기능을 물려받아 필요한 부분을 확장하는 클래스다.
3. MoreFourCal(FourCal)에서 괄호 안 FourCal은 무엇을 뜻하는가?
MoreFourCal이 FourCal을 상속받는다는 뜻이다. 즉, FourCal이 부모 클래스라는 표시다.
4. MoreFourCal이 add()를 사용할 수 있는 이유는 무엇인가?
add()가 부모 클래스 FourCal에 이미 정의되어 있고, 자식 클래스 MoreFourCal이 그 기능을 물려받았기 때문이다.
5. 상속은 왜 코드 중복을 줄이는 데 도움이 되는가?
공통 기능을 부모 클래스에 한 번만 작성하고, 자식 클래스에서는 차이 나는 부분만 추가하면 되기 때문이다. 같은 메서드를 여러 클래스에 반복해서 적지 않아도 된다.
6. 자식 클래스에 __init__이 없어도 객체를 만들 수 있는 이유는 무엇인가?
부모 클래스의 생성자를 그대로 물려받을 수 있기 때문이다. 그래서 자식 클래스가 생성자를 따로 정의하지 않아도 부모의 초기화 방식을 사용할 수 있다.
한 줄 정리
오늘은 상속을 통해 이미 만들어 둔 클래스를 버리지 않고 재사용하면서, 필요한 기능만 덧붙여 더 큰 구조로 확장하는 방법을 처음 제대로 이해한 날이었다.
Community
Comments
Comments appear immediately. Use report if something needs review.
No comments yet.