[Java] 클래스의 상속 (상속의 기본)

정보구니·2021년 12월 30일
0

Java

목록 보기
32/39
post-thumbnail

상속


  • 연관된 일련의 클래스들에 대해 상속을 적용하면 공통적인 규약을 정의할 수 있다.
  • 상속은 코드의 재활용을 목적으로 사용하는 문법이 아니다.
  • 자바는 단일 상속만을 지원한다.
    ( 한 클래스에서 상속할 수 있는 최대 클래스의 수는 한개! )



🔎 상속관련 용어 정리

  • 상속의 대상이 되는 클래스 : 상위 클래스, 부모 클래스, (기초 클래스)
  • 상속을 하는 클래스 : 하위 클래스, 자식 클래스, (유도 클래스)



🔎 상속의 UML 표현

  • 채워진 화살표는 상속을 의미하며, 화살표가 가리키는 박스가 상위 클래스를 의미한다.






상속의 기본 특성

🔎 상속의 기본 구조

class <하위 클래스이름> extends <상위 클래스이름>


// 예시
class Man { // 상위 클래스
    ...
} 

class BusinessMan extends Man { // 하위클래스
    ...
} 



🔎 상속의 효과

  • 상속관계일 경우 하위 클래스에서 상위 클래스의 멤버(인스턴스변수, 인스턴스메소드)에 접근이 가능해진다.
  • 상속관계라도, 상위 클래스의 멤버가 private으로 선언된 경우는 접근이 불가능하다.
class Man {	
	String name;
	
	public void tellYourName() {
		System.out.println("My name is " + name);
	}	
}

class BusinessMan extends Man {
	String company;
	String position;
	
	public void tellYourInfo() {
		System.out.println("My company is " + company);
		System.out.println("My position is " + position);
		tellYourName();  // 상속관계이므로 상위 클래스 멤버에 이름만으로 접근 가능
	}	
}

class MyBusinessMan {	
	public static void main(String[] args) {
		BusinessMan man = new BusinessMan("jolly", "자취 컴퍼니", "Intern"); // 하위클래스 인스턴스 생성
		man.tellYourInfo();
	}
}


// 출력 결과
My company is 자취 컴퍼니
My position is Intern
My name is jolly

  • 상속관계를 가지면 하위 클래스 인스턴스에 하위클래스 멤버 뿐만 아니라 상위클래스의 멤버도 같이 존재한다고 생각하면 된다.
    ( 그렇기 때문에 직접 접근이 가능한 것! )






상속과 생성자

  • 상속을 적용하면 하위 클래스의 생성자에서도 상위 클래스의 멤버변수에 대한 초기화를 포함시켜줘야 한다.

  • 이 경우 모든 멤버의 초기화는 이뤄지지만, 생성자를 통한 초기화 원칙에는 어긋난다.
    (모든 멤버는 그 멤버가 속한 클래스의 생성자를 통해서 초기화 되는 것이 이상적)

  • 좋은 코드를 만들기 위해 자식 클래스에서 직접 부모클래스를 초기화 하는 것이 아닌 초기화를 위한 인자만 받아주고 상위클래스의 생성자의 생성자를 호출하는 방법을 사용한다.


class Man {	
	String 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) {
		// 상위 클래스 Man의 멤버 초기화
		this.name = name;
		
		// 클래스 BusinessMan의 멤버 초기화
		this.company = company;
		this.position = position;
	}
	
	public void tellYourInfo() {
		System.out.println("My company is " + company);
		System.out.println("My position is " + position);
		tellYourName();  // 상속관계이므로 상위 클래스 멤버에 이름만으로 접근 가능
	}	
}

class MyBusinessMan {	
	public static void main(String[] args) {
		BusinessMan man = new BusinessMan("jolly", "자취 컴퍼니", "Intern"); // 하위클래스 인스턴스 생성
		man.tellYourInfo();
	}
}


// 출력 결과
My company is 자취 컴퍼니
My position is Intern
My name is jolly





🔎 상속관계에 있는 생성자의 호출관계

  • 하위 클래스 생성자에서는 반드시 상위 클래스의 생성자를 호출하도록 되어 있다.
  • 하위 클래스의 인스턴스 생성 시 상위 클래스의 생성자가 먼저 호출되고, 하위 클래스의 생성자가 호출된다.
  • 하위 클래스 생성자 내에 상위 클래스 생성자 호출문이 생략되어 있어도, 컴파일러가 자동으로 호출되도록 해준다.
class SperCls {
	public SperCls() { // 상위 클래스 생성자
		System.out.println("I'm Super Class");
	}
}

class SubCls extends SperCls {
	public SubCls() { // 하위 클래스 생성자
		System.out.println("I'm Sub Class");
	}
}

class SuperSubConExam {
	public static void main(String[] args) {
		new SubCls(); // 하위 클래스의 인스턴스 생성
	}
}


// 출력 결과
I'm Super Class  // 따로 상위 클래스 생성자를 호출하지 않았지만, 하위 클래스보다 먼저 호출된 것을 확인
I'm Sub Class





🔎 상위 클래스 생성자 명시적 호출방법

  • 명시적으로 상위 클래스를 호출하기 위해서는 하위클래스의 생성자에서 상위클래스의 생성자를 호출하도록 예약된 키워드인 super를 사용한다.
  • super는 생성자 내에서만 사용가능한 키워드이다.

class SuperCls {
	// 상위 클래스 생성자 오버로딩
	public SuperCls() {
		System.out.println("생성자 : SupeCls()");
	}
	
	public SuperCls(int i) {
		System.out.println("생성자 : SupeCls(int i)");
	}
	
	public SuperCls(int i, int j) {
		System.out.println("생성자 : SupeCls(int i, int j)");
	}
}

class SubCls extends SuperCls {
	// 하위 클래스 생성자 오버로딩
	public SubCls() {
		super(); // 상위 클래스의 생성자를 지정 및 호출
		System.out.println("생성자 : SubCls()");
	}
	
	public SubCls(int i) {
		super(i); // 상위 클래스의 생성자를 지정 및 호출
		System.out.println("생성자 : SubCls(int i)");
	}
	
	public SubCls(int i, int j) {
		super(i, j); // 상위 클래스의 생성자를 지정 및 호출
		System.out.println("생성자 : SubCls(int i, int j)");
	}
}

class SuperSubCon {
	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();
	}
}


// 출력 결과
1. 
생성자 : SupeCls()
생성자 : SubCls()

2. 
생성자 : SupeCls(int i)
생성자 : SubCls(int i)

3. 
생성자 : SupeCls(int i, int j)
생성자 : SubCls(int i, int j)









클래스(static) 변수, 메소드와 상속


  • 클래스 변수와 클래스 메소드는 인스턴스에 속하지 않는, 딱 하나만 존재하는 변수와 메소드이기 때문에 상속의 대상이 아니다.
  • 하지만, 접근 수준 지시자에 따라 상위클래스 뿐만 아니라 하위클래스에서도 이름만으로 접근은 가능하다.
    ( private으로 선언 될 경우 접근 불가능! )

class SuperCls {
	protected static int count = 0;  //  클래스 변수 선언
	
	public SuperCls() {
		count++;
	}
}

class SubCls3 extends SuperCls { 
	public void showCount() {
		System.out.println(count); // 상위 클래스에 위치한 클래스 변수 count에 접근
	}
}

public class SuperSubStatic {
	public static void main(String[] args) {
		new SuperCls(); // count 값 1 증가
		new SuperCls(); // count 값 1 증가
		
		// 하위 클래스 인스턴스 생성과정에서 상위클래스 생성자 호출됨
		SubCls3 obj = new SubCls();  // count 값 1 증가
		obj.showCount();
	}
}


// 출력 결과
3









참고
열혈 자바 ch14 (클래스의 상속1)

0개의 댓글