[공부 필기] Java 기본 공부하기 (13)
공부 중인 강의 : 윤성우 선생님, 윤성우의 열혈 Java 프로그래밍 강의, https://cafe.naver.com/cstudyjava
1. 상속 (드디어 상속이다)
- 상속은 코드 재활용을 위한 문법? No
- 상속은 재활용(코드 재사용)을 목적으로 정의된 문법이 아니라고 함 (물론, 단순히 보기에는 재활용처럼 보이기는 함)
- 상속은 연관되어 있는 일련의 클래스들에 대해서 공통적인 규약을 정의하는 것임
→ 상속을 쓰더라도 이 의미가 없으면 상속이 아님
→ 개인적으로 생각하기에 위의 문장은 이런 의미와 유사한 것 같음
* 서로 다른 지역에 사는 중학생들이 여러명 있다고 가정 (= 각자 다른 곳에 사는 클래스들)
* 이들은 모두 "중학교"를 다닌다는 공통점이 있음 (= 연관이 있음)
* 이들에게 모두 "교복을 가지고 있어야 한다"는 약속을 적용하려고 함 (= 공통적인 규약을 정의)
→ 이처럼 A, B, C 라는 클래스는 어떠한 연관이 있고
그 클래스들에게 공통적인 규약을 정의 해야할 때 "상속"을 사용하는게 아닐까 싶음 (추측)
# '상속이 재활용이 아닌' 이유에 대해 이해해보기
- 보통 "공학"(기계공학, 건축공학 등)에는 "표준"이라는 것이 존재하고
이 "표준을 근거로 해서 재활용"이라는 것이 어느정도 가능함
→ 즉, 표준화 덕분에 재활용이 가능해졌다는 의미
- 하지만 SW는 아직 재활용이 어려움
→ 여기에서 말하는 "재활용"은 (코드 레벨에서) 하나도 수정하지 않고 그대로 가져와 사용할 수 있는 것을 말함
→ SW 분야는 코드를 하나도 수정하지 않고 그대로 가져와 사용하는 것이 아직 어려움..
- 때문에 SW의 세계는 다른 프로그램의 코드를 수정 없이 그대로 가져와 사용하는 것보다 다시 코딩하는데 더 안정적이라고 함
→ 아직까지는 그렇다고 함..
→ "컴포넌트"라는 개념을 도입해서 시스템을 구축하면 'SW도 재활용이 가능할 것이다'라는 연구가 나오고 있다고는 함
- 그렇기 때문에 상속이 "재활용"을 위한 문법이라고 하기 어렵다고 함..
- 참고 자료 :
# SW - 코드 재사용에 대한 조사
- 이 강의는 2017년 강의라 트렌드 반영이 안된 듯 하여 최근의 코드 재사용에 대한 추세를 찾아봄
- Architectural patterns, Design patterns, Component-based development, Application frameworks, Legacy system wrapping 등의 방법이 있다고 하는데.. 너무 어려워서 아직 이해를 못하겠음..
- 출처 :
2. 상속 기본 특성
- 코드 레벨에서의 '상속'
→ extends 키워드를 이용함
→ 아래 코드는 "Student 클래스는 Person 클래스를 상속한다"는 의미
→ Student 인스턴스 내부에서 Person 인스턴스의 멤버 변수/메소드에 접근할 수 있음
class Person {
...
}
class Student extends Person {
...
}
- 코드 레벨에서의 '상속' 효과 알아보기
→ Student 인스턴스를 생성하면,
해당 인스턴스에는 Person의 인스턴스 멤버(변수, 메소드들 모두)와 Student 인스턴스 멤버(변수, 메소드들 모두)가
하나로 묶여서 형성됨 (하나의 인스턴스 안에 함께 존재하는 것)
→ 그림으로 표현하면... 이런 모습? (그림1 참고)
- 하지만, 부모 클래스가 private이면 조금 다름
→ 하나의 인스턴스 안에 변수/메소드들이 함께 존재하는 것은 똑같음
→ 다만, Student 인스턴스가 Person 인스턴스 멤버 변수/메소드에 접근은 하지 못함
- 보통 Person 클래스를 "상위 클래스"(또는 기초 클래스, 부모 클래스) 라고 함
그리고 Student 클래스를 "하위 클래스"(또는 유도 클래스, 자식 클래스) 라고 부름
→ Person은 "상위 클래스"라고 하고 Student는 "자식 클래스"라고 하는 등 크로스해서 섞어서 용어를 사용하지는 않음
→ "상위 클래스"라는 용어의 짝은 "하위 클래스"이고
"부모 클래스"라는 용어의 짝은 "자식 클래스"임
- 상속을 UML로 표현하면 이렇게 표현 가능함
→ 기회가 되면 "UML"을 공부하는 것도 괜찮음
3. 상속 & 생성자
- 아래와 같은 상황이 있다고 가정
→ Student 생성자에서 인자로 이름과 번호를 전달받고 부모 클래스의 멤버 변수인 "name"을 초기화 해야함
public class Person {
private String name;
Person(String name) {
this.name = name;
}
public void printYourName() {
System.out.println(name);
}
}
public class Student extends Person {
private int number;
// Student 인스턴스를 생성해서 생성자에서 부모 클래스의 name 변수를 초기화하고 싶음
...
- 단순하게 생각하면?
→ 아래와 같이 코드를 작성
public class Student extends Person {
private int number;
Student(String name, int num) {
this.name = name; // 목적: 부모 클래스 Person의 멤버변수 name을 초기화 하고 싶음
number = num;
}
}
→ 하지만 이렇게 실행하면 "에러가 발생함" (그림2 참고)
* 사실 이 방법을 적용할 때, 운 좋게(?) 오류가 발생하지 않았더라도 좋은 방법은 아님
* 왜냐하면,
클래스(여기에서는 Person)의 멤버변수는 그 클래스(Person)의 생성자 안에서 초기화 시켜주는 것이 가장 좋기 때문
- 이런 오류가 발생하는 이유는 이러함
→ 우선 다시 복습해야할 내용 :
* 디폴트 생성자(기본 생성자)는 "생성자가 전혀 정의되어 있지 않을 때 컴파일러가 자동으로 생성해서 넣어주는 것"임
* 개발자가 하나라도 생성자를 정의해준게 있다면 컴파일러는 디폴트 생성자를 만들지 않음 (그림3 참고)
* 즉, 생성자가 오버로딩 되어 있으면 컴파일러는 디폴트 생성자를 만들지 않음
→ Java 문법에는 규칙이 있음
→ 자식 클래스의 생성자는 "반드시" 부모 클래스의 생성자를 먼저 자동으로 호출함
→ 만약 개발자가 명시적으로 부모 클래스의 생성자를 호출하지 않았다면?
컴파일러가 자동으로 생성자 안의 가장 첫 줄에 부모 생성자를 호출하는 코드를 넣어줌
→ 이제 위의 오류가 발생한 상황으로 가보자
* 컴파일러는 자식 클래스의 생성자 안에 자동으로 부모 클래스의 생성자를 호출하는 코드를 넣어줌
* 이때 부모 클래스의 기본 생성자를 호출하는 코드를 넣어주게됨
* 문제는 부모 클래스에는 "명시적으로" 기본 생성자를 정의해두지 않았음
* 이 때문에 에러가 발생함
참고한 자료 : https://blog.daum.net/genesis_8/9
- 따라서 이 오류를 해결하는 방법은 두가지임
→ 첫번째. 부모 클래스 Person에게 기본 생성자를 명시적으로 추가해줌
class Person {
public String name;
Person() {
}
...
→ 두번째. 자식 클래스 Student에서 부모 클래스의 생성자를 호출할 때, 인자를 전달하면서 호출함
* super 키워드는 상위 클래스의 생성자를 호출하는 기능을 함
* super 키워드는 하위 클래스의 생성자에서만 사용할 수 있음
public class Student extends Person {
private int number;
Student(String name, int num) {
super(name); // 부모 생성자를 호출한다. 이때 인자는 name을 전달한다. 는 의미
number = num;
}
...
→ 개인적으로 생각하기에,
"클래스 멤버변수는 해당 클래스의 생성자에서 초기화 해주는 것이 가장 이상적"이라고 강의에서 말했기 때문에
첫번째 방법보다는 두번째 방법이 좀 더 괜찮은 방법이지 않을까싶음
4. 상속 - 기타 특징
- 상속은 "단일 상속"만 지원함
→ Student 클래스가 Person 클래스와 Woman 클래스를 동시에 상속하는 것 = 안됨
→ JAVA는 다중 상속을 지원하지 않는다고 함
→ 한 클래스가 상속할 수 있는 최대 클래스의 수는 한 개임
- 하지만, 이런 경우는 가능함
→ Person 클래스와 Woman 클래스와 Student 클래스가 있음
→ 부모 클래스 : Person
자식 클래스 : Woman
→ 부모 클래스 : Woman
자식 클래스 : Student
→ Woman 클래스는 Person의 "자식 클래스"이자 Student의 "부모 클래스"임
→ 이처럼 A라는 클래스의 부모 클래스이자 B라는 클래스의 자식 클래스가 되는 관계를 만들수는 있음
(클래스들을 상속 관계로 만들다보면 체인처럼 엄청 길어질수도..)