Cute Running Puppy

Language/[Java] 자바 완전 정복

4주차_10. 클래스의 상속과 다형성

R.silver 2022. 2. 10. 20:11
반응형

클래스의 상속의 개념과 문법적 특징 

상속

다른 클래스의 멤버를 이어받는 기능 

상속의 장점

1. 코드의 중복성 제거

2. 클래스의 다형적 표현이 가능 

   (다형성: 하나의 객체를 여러 가지 모양으로 표현할 수 있는 특성)

상속 문법

class 자식_클래스 extends 부모_클래스 {
    ...
}

 

자바에서는 다중 상속은 불가능하다 (부모 클래스를 2개 이상 상속받는 것)

-> 다중 상속을 허용한다면 모호성이 발생할 수 있기 때문 (상속 받는 클래스 안의 내용이 겹칠 때)

부모 클래스를 상속 받는 자식 클래스는 여러 개가 와도 된다. 

생성자의 상속 여부

상속을 수행하면 부모의 모든 멤버를 내려 받는다. 

여기서 멤버는 생성자를 제외한 필드, 메서드, 이너 클래스를 말한다. 

생성자는 절대로 상속되어서는 안된다. 

(클래스 내부에는 필드, 메서드, 생성자, 이너 클래스 외에 어떤 것도 올 수 없다. 

그런데 생성자도 상속 받을 때 같이 상속받게 된다면 

상속받은 클래스 내부에 A() {}의 형태의 코드가 생성된다. 

이 코드는 소괄호와 중괄호가 있기에 필드와 이너 클래스가 될 수 없으며

상속받은 클래스 (B)와 이름이 달라 생성자라고도 할 수 없다.

또한 리턴 타입이 없기에 메서드라고도 할 수 없다. 

이러한 문제점 때문에 생성자는 상속받을 수 없고, 상속해서도 안된다. )

객체의 다형적 표현

A 클래스를 상속 받아 B 클래스를 생성한다고 하면 (B -> A)

 

A a1 = new A(); // A는 A이다. 
A a2 = new B(); // B는 A이다.

 

이 코드와 같이 자식 클래스의 객체를 부모 클래스 타입으로 선언할 수 있다. 

객체의 타입 변환

객체의 업캐스팅과 다운 캐스팅

업 캐스팅: 좁은 쪽에서 넓은 쪽으로 캐스팅

다운 캐스팅: 넓은 쪽에서 좁은 쪽으로 캐스팅

 

객체는 항상 업 캐스팅이 가능하므로 명시적으로 적어주지 않아도 된다. 

그러나 다운 캐스팅을 하기 위해서는 개발자가 명시적으로 코드를 넣어주어야 한다. 

 

객체를 다운 캐스팅하는 것에는 자료형을 다운 캐스팅 하는 것에서 발견할 수 없는 예외가 발생한다

(예외: ClassCastException)

자식 클래스에 있는 기능이 없기에 부모 클래스를 다운 캐스팅할 수 없다 

(학생 -> 사람 일 때 사람을 학생으로 다운 캐스팅할 수 없다.)

 

캐스팅의 가능 여부는 어떤 타임으로 선언되어 있는지가 중요하지 않다.

어떤 생성자로 생성되었는지가 중요하다. 

선언 타입에 따른 차이점 

class A {
	int m = 3;
    void abc() {
    	System.out.println("A");
    }
    
class B extendes A {
	int n = 4;
    void bcd() {
    	System.out.println("B");
    }
    
// B의 객체를 B 타입으로 선언했을 때
B b = new B();
System.out.println(b.m); // 3
System.out.println(b.n); // 4
b.abc(); // A
b.bcd(); // B

// B의 객체를 A 타입으로 선언했을 때
A a = new B();
System.out.println(a.m); // 3
System.out.println(a.n); // error
b.abc(); // A
b.bcd(); // error

 

B의 객체를 A 타입으로 선언했을 때 (A a = new B();)

B() 상성자로 객체를 생성한 것은 동일하기에 힙 메모리에 생성되는 객체의 모양은 동일하다. 

그러나 참조 변수가 A 타입으로 선언되어있으므로 실제 힙 메모리에 B 객체가 있더라도 

참조 변수 a는 A 객체만을 가리킨다. 

캐스팅 가능 여부를 확인하는 instanceof 키워드

참조_변수 instanceof 타입 // boolean으로 return 

잘못된 다운 캐스팅으로 예외가 발생하는 것을 막기 위해 보통 다운 캐스팅을 수행할 때 instanceof를 사용하여 캐스팅 여부를 확인한 뒤 캐스팅을 진행한다. 

메서드 오버 라이딩

메서드 오버 라이딩

부모 클래스에서 상속받은 메서드와 동일한 이름의 메서드를 재 정의하는 것 

적용 조건

1.  부모 클래스의 메서드와 시그너처 및 리턴 타입이 동일해야 한다. 

2. 부모 클래스의 메서드보다 접근 지정자의 범위가 같거나 넓어야 한다. 

 

인스턴스 필드와 정적 멤버의 중복

메서드가 아닌 인스턴스 필드와 정적 멤버는 오버 라이딩할 수 없다

 

class A {
	int m = 3;
}

class B extends A {
	int m = 4;
}

//main 함수
{
	A aa = new A();
    B bb = new B();
    A cc = new B();
    
    System.out.println(aa.m); // 3
    System.out.println(bb.m); // 4
    System.out.println(cc.m); // 3
}

 

supter 키워드와 super() 메서드

this this() super super()
자신의 객체 자신의 생성자 부모의 객체 부모의 생성자

부모의 객체를 가리키는 super 키워드

필드 명의 중복 또는 메서드 오버 라이딩으로 가져진 부모의 필드 도는 메서드를 호출하기 위해 사용

실 사용 예시

부모 클래스의 초기화 기능에 100 줄의 코드가 있고 

자식 클래스에서 부모 클래스의 초기화 기능에 1줄을 추가하고 싶을 때

super 키워드를 사용하여 자식 클래스의 메서드에서 부모 클래스의 메서드를 호출하고 

추가할 코드 한 줄만 작성하여 부모 클래스의 코드에 1줄만 추가할 수 있다. 

부모 클래스의 생성자를 호출하는 super() 메서드

모든 생성자의 첫 줄에는 반드시 this() 또는 super()가 있다 (둘을 동시에 사용할 수 없다)

최상위 클래스 Object

자바의 모든 클래스는 object를 상속받는다. 

object 클래스의 주요 메서드

반환 타입  메서드명 주요 내용
String toString() 객체 정보를 문자열로 출력
boolean equals(Object obj) 스택 메모리 값 비교
int  hashCode() 객체의 위치와 연관된 값
void  wait()
wait(long timeout)
wait(long timeout, int nanos)
현재의 스레드를 wait 상태로 전환
동기화 블록에서만 사용 가능 

 

 

 

반응형