[Java] 클래스의 상속 (오버라이딩)

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

Java

목록 보기
33/39
post-thumbnail

상속


🔎 상속의 특성

  • 자식 클래스는 부모 클래스의 모든 특성(변수, 메소드)을 지니며, 자식 클래스 만의 추가적인 특성(변수, 메소드)을 더 가진다.
  • 자식 클래스는 부모 클래스의 모든 기능을 할 수 있다.



🔎 상속의 기본 조건 (IS-A)

  • 상속 관계를 형성하기 위한 두 클래스는 IS-A 관계에 있어야 한다.
  • IS-A 관계란 "~은 ~이다"가 성립하는 관계를 의미한다.
    - 예) 스마트폰 is a 모바일폰 ➡ "스마트폰은 일종의 모바일폰이다"
  • IS-A 관계를 갖지 않는 두 클래스가 상속으로 연결되어 있다면, 적절한 상속인지 의심해볼 필요가 있다.!

class MobilePhone {
	protected String number;
	
	public MobilePhone(String number) {
		this.number = number;
	}
	
	public void answer() {  // 전화 받기 기능
		System.out.println(number + "의 전화를 받습니다.");
	}
}

/* 상속 관계 (IS-A 관계)
 * 자식클래스(SmartPhone) ➡ 부모클래스(MobilePhone)
 */
class SmartPhone extends MobilePhone {
	private String androidVer; // 안드로이드 운영체제 버전
	
	public SmartPhone(String number, String ver) {
		super(number);
		androidVer = ver;
	}
	
	public void playApp() {  // 앱 실행 기능
		System.out.println(androidVer + "버전으로 앱을 실행합니다.");
	}
}


class ISAExam {
	public static void main(String[] args) {
		SmartPhone phone = new SmartPhone("010-1111-2222", "Nougat");
		phone.answer(); // 자식 클래스형의 참조변수를 통해 부모 클래스 멤버에 접근 가능
		phone.playApp(); 
	}
}


// 결과 출력
010-1111-2222의 전화를 받습니다.
Nougat버전으로 앱을 실행합니다.









참조변수의 참조 가능성


  • 자식 클래스의 인스턴스는 자식 클래스형 참조변수와 부모 클래스형 참조변수 둘 다 참조 가능하다.
    ( 역으로 부모 클래스의 인스턴스를 자식 클래스형 참조변수가 참조하는 것은 불가능 )
  • 부모 클래스형 참조변수가 자식클래스의 인스턴스를 참조할 경우,
    부모 클래스형 참조변수는 부모 클래스의 메소드에만 접근할 수 있다. ( 자식 클래스의 메소드에 접근 불가능! )
  • 접근을 제한하는 이유는 참조변수의 형을 기준으로 접근 가능한 멤버를 제한하는 것이 코드를 단순하게 하기 때문이다.

class Cake {
    public void sweet() {...}
}

class ChesseCake extends Cake {
    public void milky() {...}
}

class StrawberryCheeseCake extends ChesseCake {
    public void sour() {...}
}
Cake cake1 = new StrawberryCheeseCake();  // Cake형 참조변수가 StrawberryCheeseCake 인스턴스 참조
CheeseCake cake2 = new StrawberryCheeseCake();  // CheeseCake형 참조변수가 StrawberryCheeseCake 인스턴스 참조
StrawberryCheeseCake cake2 = new StrawberryCheeseCake();

cake1.sweet();
// cake1.milky();  // 컴파일 에러발생
// cake1.sour();   // 컴파일 에러발생

cake2.sweet();
cake2.milky();
// cake2.sour();   // 컴파일 에러발생

cake3.sweet();
cake3.milky();
cake3.sour();





🔎 참조변수 간 대입과 형 변환

  • 부모클래스의 참조변수가 자식클래스의 인스턴스를 참조하는 경우,
    해당 참조변수를 다시 자식클래스의 참조변수에 담는 것은 불가능하다. ( 형변환이 필요! )
CheeseCake cake1 = new CheeseCake();
Cake cake2 = cake2;  // 가능

Cake cake3 = new CheeseCake();
// CheeseCake cake4 = cake3; // 불가능
CheeseCake cake4 = (CheeseCake) cake3;  // 형변환









메소드 오버라이딩


  • 부모 클래스의 메소드와 자식 클래스의 메소드의 반환형, 메소드의 이름, 메소드의 매개변수가 같을 때 메소드 오버라이딩이 성립한다.
  • 메소드가 오버라이딩 관계에 있을 때 자식 클래스의 메소드가 부모 클래스의 메소드를 '가렸다'라고 표현한다.
  • 부모 클래스의 참조변수가 자식클래스의 인스턴스를 참조한 경우,
    부모 클래스의 메소드에만 접근이 가능하지만, 오버라이딩 된 경우 자식클래스 메소드에 가려졌기 때문에 자식 클래스 메소드가 대신 호출된다.

class Cake {
	public void yummy() {
		System.out.println("yummy Cake");  // 오버라이딩 당함
	}
}

class CheeseCake extends Cake {
	public void yummy() {
		System.out.println("yummy CheeseCake");  // Cake(부모 클래스)의 yummy 메소드를 오버라이딩 함
	}
}

class MethodOverridingExam {
	public static void main(String[] args) {
		Cake c1 = new CheeseCake();
		CheeseCake c2 = new CheeseCake();
		
		c1.yummy(); // Cake형 참조변수를 통해서도 오버라이딩 한 CheeseCake의 yummy 메소드를 호출
		c2.yummy(); // CheeseCake의 yummy 메소드를 호출
	}
}


// 출력 결과
yummy CheeseCake
yummy CheeseCake





🔎 오버라이딩 된 메소드 호출하는 방법

  • 외부에서는 오버라이딩 된 메소드를 호출 할 수 없다. ( 오버라이딩 한 메소드가 대신 호출되기 때문에)
  • 자식 클래스에서만 부모 클래스의 메소드(오버라이딩 당한=가려진)에 접근할 수 있다.
  • super.를 이용해 접근이 가능하다.
    ( super.는 "내가 상속하고 있는 부모 클래스의"라는 의미를 갖는다! )

class Cake {
	public void yummy() {
		System.out.println("yummy Cake");
	}
}


class CheeseCake extends Cake {
	public void yummy() {
		super.yummy();  // Cake의 오버라이딩 된 yummy 메소드 호출
		System.out.println("yummy CheeseCake");
	}
	
	public void tasty() {
		super.yummy();  // Cake의 오버라이딩 된 yummy 메소드 호출
		System.out.println("testy CheeseCake");
	}
}


class MethodOverridingSuperExam {
	public static void main(String[] args) {
		CheeseCake c = new CheeseCake();
		
		c.yummy();
		c.tasty(); 
	}
}


// 출력결과
yummy Cake
yummy CheeseCake
yummy Cake
testy CheeseCake





🔎 인스턴스 변수와 클래스 변수는 오버라이딩 대상일까 ?

  • 인스턴스 변수와 클래스 변수는 오버라이딩의 대상이 아니다. (인스턴스 메소드만 오버라이딩 대상!)
  • 참조변수의 형에 따라 접근하는 멤버가 결정된다.
class Cake {
    public int size;
    ...
}

class ChesseCake extends Cake {
    public int size;
    ...
}
CheeseCake c1 = new CheeseCake();
c1.size = ...  // CheeseCake의 size에 접근

Cake c2 = new CheeseCake();
c2.sizw = ...  // Cake의 size에 접근









instanseof 연산자


  • 연산자 instanseof참조변수가 참조하는 인스턴스의 클래스참조하는 인스턴스가 상속하는 클래스를 묻는 연산자이다.

  • 기본 구조

if (참조변수 instanceof 클래스이름)
    ...
  • 예시
    if (c instanceof Cake)
    - c가 참조하는 인스턴스가 Cake의 인스턴스면 true 반환
    - c가 참조하는 인스턴스가 Cake를 상속하는 자식 클래스의 인스턴스면 true 반환
    - 그렇지 않으면 false 반환









참고
열혈 자바 ch15 (클래스의 상속2)

0개의 댓글