14-1 상속의 기본 문법 이해
( sw공학에서 자주 언급되는 내용. 아직 sw분야는 재활용이 어려움. 코드 레벨에서 얘기함)
--> 연괸된 일련의 클래스들에 대해 공통적인 규약을 정의할 수 있다.
Ex) A / B / C ( class ) -> 클래스들이 서로 다르면 어떤 규약 & 규칙을 적용하는데 어려움이 있음. 각 class마다 적용될 규칙 & 규약이 다르다.
여기 상속을 적용하면 공통적인 규약 & 규칙을 적용할 수 있다.
l 상속의 가장 기본적인 특성
- 상속 (Code level) : 기존에 정의된 클래스에 메소드와 변수를 추가 à 새로운 클래스 정의
- class Man {
String name; // 인스턴스 변수
public void tellYourName() { // 인스턴스 메소드
System.out.println("My name is " + name);
}
}
< 위의 클래스를 물려 받아서 새로운 클래스를 정의 >
public class BusinessMan extends Man { // Man을 상속하는 BusinessMan
String company;
String position;
public void tellYourInfo() {
System.out.println("My company is " + company);
System.out.println("My position is " + position);
tellYourName(); // Man 클래스를 상속했기 때문에 호출 가능! 메소드 & 인스턴스 변수 등
}
}


l 상속과 생성자
à ‘기본적으로 클래스 안에 존재하는 인스턴스 변수를 초기화 하는 것이 목적’
< 앞 Man클래스에 인스턴스 변수의 초기화를 위한 생성자 정의 >
class Man {
String name; // 인스턴스 변수
public Man(String name) {
this.name = name; // 생성자 내에서 위 name을 적절히 초기화 하도록 정의
// String name이 private로 선언되지 않았기 때문에 직접 접근 가능
}
public void tellYourName() { // 인스턴스 메소드
System.out.println("My name is " + name);
}
}
< Business 클래스에 인스턴스 변수의 초기화를 위한 생성자 정의 >
public class BusinessMan extends Man { // Man을 상속하는 BusinessMan
String company;
String position;
// 모든 인스턴스 변수를 적절히 초기화하도록 아주 잘 정의되어 있음.
// --> 회사랑 직급은 초기화가 되는데 이름 정보가 초기화가 안된다.
// 생성자 내에서 name에 접근하는 코드를 만들어놓지 X.
public BusinessMan(String company, String position) {
this.company = company;
this.position = position;
}
public void tellYourInfo() {
System.out.println("My company is " + company);
System.out.println("My position is " + position);
tellYourName(); // Man 클래스를 상속했기 때문에 호출 가능! 메소드 & 인스턴스 변수 등
}
}
// --> 모든 멤버의 초기화는 이루어진다. 그러나 생성자를 위한 초기화 원칙에는 어긋남.
- 상위 클래스 Man, 그리고 이를 상속하는 하위 클래스인 BusinessMan에도 적절한 생성자가 정의 되어 있다.
- 문제 ) BusinessMan의 인스턴스 생성 -> 그 안에는 Man 클래스의 상속으로 인해 name변수가 초기화되지 않는 문제가 발생한다.
- String name;-->상속으로 인해 BusinessMan 클래스의 멤버가 된 변수
< BusinessMan생성자에서 위 변수의 초기화 진행 >
l MyBusinessMan
l class Man {
String name; // 인스턴스 변수
public void tellYourName() {
System.out.println("My name is " + name);
}
}
class BusinessMan extends Man { // Man을 상속하는 BusinessMan
String company;
String position;
// man의 멤버 name을 초기화할 수 있는걸 인자로 받아버림.
public BusinessMan(String name, String company, String position) {
this.name = name; // String name을 초기화해주는 코드를 넣음
// this --> 이 인스턴스의 멤버 name
this.company = company;
this.position = position;
}
public void tellYourInfo() {
System.out.println("My company is " + company);
System.out.println("My position is " + position);
tellYourName(); // Man 클래스를 상속했기 때문에 호출 가능! 메소드 & 인스턴스 변수 등
}
}
class MyBusinessMan {
public static void main(String[] args) {
BusinessMan man = new BusinessMan("YOON", "Hybrid ELD", "Staff Eng.");
man.tellYourInfo();
}
}

< 상속 관계에 있는 생성자의 호출 관계 >
class SuperCLS {
public SuperCLS() { // 생성자
System.out.println("I'm Super Class");
}
}
class SubCLS extends SuperCLS {
public SubCLS() { // 생성자
System.out.println("I'm Sub Class");
}
}
class SuperSubCon {
public static void main(String args[]) {
new SubCLS();
}
}

-> 하위 클래스의 인스턴스 생성 시 상위 클래스, 하위 클래스의 생성자 모두 호출됨.
-> 하위 클래스의 인스턴스 생성 시 상위 클래스의 생성자가 먼저 호출된다.
- 아래 코드에서 SuperCLS()는 SuperCLS의 생성자가 이 순간에 호출됨을 의미.
class SubCLS extends SuperCLS {
public SubCLS() {
SuperCLS(); // 상위 클래스의 생성자가 이 순간에 호출됨을 의미.
System.out.println("I'm Sub Class");
}
}
- 하위 클래스의 생성자에서 상위 클래스의 생성자를 명시적으로 호출하지 않으면,
인자를 받지 않는 생성자가 자동으로 호출.
상위 클래스의 생성자는 어떻게 명시적으로 호출? (다음)
- super : 상위 클래스의 생성자 호출
< super 클래스를 사용하여 상위 클래스의 명시적 호출 >
class SuperCLS {
public SuperCLS() {
System.out.println("Con : SuperCLS()" );
}
public SuperCLS(int i) {
System.out.println("Con : SuperCLS(int i)");
}
public SuperCLS(int i, int j) {
System.out.println("Con : SuperCLS(int i, int j)");
}
}
class SubCLS extends SuperCLS {
public SubCLS() {
System.out.println("Con : SubCLS()");
}
public SubCLS(int i) {
super(i); // 상위 클래스의 생성자 지정 및 호출
System.out.println("Con : SubCLS(int i)");
}
public SubCLS(int i, int j){
super(i,j); // 상위 클래스의 생성자 지정 및 호출
System.out.println("Con : SubCLS(int i , int j)");
}
}
public class SuperSubCon2 {
public static void main(String args[]) {
System.out.println("1. ");
new SubCLS();
System.out.println();
System.out.println("2. ");
new SubCLS(1);
System.out.println();
System.out.println("3. ");
new SubCLS(1, 2);
System.out.println();
}
}

- super(1); -> 1을 인자로 전달받을 수 있는 생성자 호출
- super(1, 2); -> 1과 2를 인자로 전달받을 수 있는 생성자 호출
è ‘ 상위 클래스의 생성자는 하위 클래스 생성자의 몸체 부분에 앞서 실행되어야 함’
super를 이용한 상위 클래스의 생성자 호출문은 생성자의 첫 문장으로 등장 해야함.
< 컴파일 오류가 발생하는 경우 >
1. Super 위치
public SubCLS(int i) {
System.out.println(~~~);
super(i); // super가 이 위치에 있으면 컴파일 오류 발생
}
2. 생성자 호출을 생략한 경우 à 생성자 호출문이 자동으로 삽입
public SubCLS() {
System.out.println("Con : SubCLS()");
}
è
public SubCLS() {
super(); // 자동으로 삽입이 된 문장
System.out.println("Con : SubCLS()");
}
l < 상속 관계에 있는 두 클래스의 적절한 생성자 정의 >
- 자바는 상속 관계에 있어도, 상위 클래스의 멤버는 상위 클래스의 생성자를 통해서 초기화하도록 유도.
(하위 클래스의 인스턴스 생성 과정 중 상위 클래스의 생성자가 호출되는 이유가 여기 있음)
< MyBusinessMan2 > : super(변수로 받는 것)
class Man {
String name;
public Man(String name){
this.name = name;
}
public void tellYourName() {
System.out.println("My name is " + name);
}
}
class BusinessMan extends Man {
String company;
String position;
public BusinessMan(String name, String company, String position) {
super(name); // 상위 클래스의 생성자 호출
this.company = company;
this.position = position;
}
public void tellYourInfo() {
System.out.println("My company is" + company);
System.out.println("My position is" + position);
tellYourName();
}
}
public class MyBusinessMan2 {
public static void main(String args[]) {
BusinessMan man = new BusinessMan("YOON", "Hybrid ELD", "Staff Eng.");
man.tellYourInfo();
}
}

- ‘ 상속 관계에 있을지라도 인스턴스 변수는 각 클래스의 생성자를 통해서 초기화 진행 ‘
< 단일 상속만을 지원하는 자바 >
--> 이는 다음과 같이 하나의 클래스가 상속할 수 있는 클래스의 수가 최대 ‘하나’라는 것.
과도하게 복잡해지는 것을 막기 위해서 !
'Java' 카테고리의 다른 글
| ch22. 제네릭(2) -1 (0) | 2022.03.10 |
|---|---|
| JAVA Programming(Ch 15. 메소드 오버라이딩) (0) | 2021.08.09 |
| JAVA Programming(Ch 13. 배열) (0) | 2021.08.09 |
| JAVA Programming(Ch 12.콘솔 출력) (0) | 2021.08.09 |
| JAVA Programming(Ch 11. 메소드 오버로딩) (0) | 2021.08.08 |