[자바의 정석] 상속

YJS·2023년 11월 17일
0
post-thumbnail

1. 자바 상속의 특징


상속이란?

기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것.

-코드의 재사용성을 높이고 중복을 제거하여 프로그램의 생산성과 유지보수에 기여

class Parent{}
class Child extends Parent{}

-조상클래스: 부모클래스, 상위클래스, 기반클래스

자손 클래스: 자식클래스, 하위클래스, 파생된클래스

출처: TCP School

→ 자손 클래스는 조상클래스의 모든 멤버를 상속받음.(자손 클래스는 항상 조상클래스보다 같거나 많은 멤버를 가짐. 상속을 거듭할 수록 멤버 개수는 늘어남)

→child 클래스에 새로운 코드가 추가되어도 조상인 Parent 클래스에는 아무런 영향이 없음.

→생성자와 초기화 블럭은 상속되지 않음. 멤버만 상속

→ 클래스간에 관계에는 형제 관계는 없음. (즉, Parent 클래스 상속받은 child1과 child2는 서로 영향 줄 수 없음)

→ 자손클래스의 인스턴스를 생성하면 조상클래스의 멤버도 함께 생성되기 때문에 따로 조상 클래스의 인스턴스를 생성하지 않고도 조상클래스의 멤버들을 사용할 수 있음.

→ 자바에서는 단일상속만 허용.

상속관계 vs 포함관계

-상속관계: is-a

-포함관계: has-a

2. super 키워드


super 참조변수

super는 자손 클래스에서 조상클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수.

→ this 와 비슷 (멤버변수와 지역변수의 이름이 같을때 구분용)

= 조상클래스로부터 상속받은 멤버와 자손 클래스 자신의 멤버 구분용으로 사용.

(조상클래스의 멤버와 자손클래스의 멤버가 중복 정의되어 서로 구별해야하는 경우에만 사용하는 것이 좋음)

→ static 메서드에서는 사용 불가. 인스턴스메서드만 사용 가능

class SuperTest{
	public static void main (String args[]){
		Child c = new Child();
		c.method();
	}
}
class Parent{
int x =10;
}
class Child extends Parent{
int x =20;
void method(){
System.out.println(x); // 20
System.out.println(this.x); // 20
System.out.println(super.x); //10

super()

조상클래스의 생성자 호출

→ 자손클래스의 인스턴스 생성시 자손 멤버와 조상 멤버가 모두 합쳐진 하나의 인스턴스가 생성됨.

이로 인해 조상클래스 멤버도 사용 가능. 이때 조상클래스 멤버의 초기화 작업이 수행되어야하므로 자손 클래스의 생성자 첫줄에 조상클래스 생성자 호출해야함.

→ object 제외한 모든 클래스의 생성자 첫줄에 생성자, this(), 또는 super()를 호출해야함. 아니면 컴파일러가 자동으로 super();생성자를 첫줄에 삽입.

3. 메소드 오버라이딩


오버라이딩이란?

조상클래스로부터 상속받은 메서드의 내용을 변경하는 것.

<오버라이딩의 조건>

자손클래스에서 오버라이딩하는 메서드는 조상클래스의 메서드와

-이름이 같아야 함.

-매개변수가 같아야함.

-변환타입이 같아야함.

→ 선언부가 일치해야함. 다만, 접근 제어자와 예외는 제한된 조건 하에서만 변경가능.

→ 접근 제어자는 조상클래스의 메서드보다 좁은 범위로 변경 불가능.

(public > protected > default > private순)

→조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없음

→ 인스턴스메서드를 static 메서드로 또는 그 반대로 변경 불가능.

cf. 오버로딩 vs 오버라이딩

-오버로딩: 기본에 없는 새로운 메서드를 추가

-오버라이딩: 상속받은 메서드의 내용을 변경하는 것.

class Parent{
	void parentMethod() {}
}

class Child extends Parent{
	void parentMethod() {} //오버라이딩
	void parentMethod(int i) {} //오버로딩

	void childMethod() {}
	void childMethod(int i) {} //오버로딩

4. 다이나믹 메소드 디스패치 (Dynamic Method Dispatch)


메서드 디스패치란?

어떤 메서드를 호출할지 결정하여 실제로 실행시키는 과정. 자바는 런타임 시 객체를 생성하고, 컴파일 시에는 생성할 객체 타입에 대한 정보만 보유. 이에따라 이 과정은 static(정적)과 dynamic(동적)으로 나뉨.

-Static Dispatch  : 컴파일 시점에서, 컴파일러가 특정 메소드를 호출할 것이라고 명확하게 알고있는 경우. (정적)

→컴파일 시 생성된 바이트 코드에도 이 정보가 그대로 남아있음.

→런타임(실행 시점)이 되지 않아도 미리 결정하는 개념.

→함수를 오버로딩하여 사용하는 경우 인자의 타입이나 리턴타입 등에 따라 어떤 메서드를 호출할지 알 수 있는 경우

public class ACar {
    public void print() {
        System.out.println("A");
    }
}

public class BCar extends ACar { //메소드 오버라이딩 - ACar상속 후 함수 재정의
    public void print() {
        System.out.println("BCar");
    }
}
//ex) 스태틱 메서드 디스패치
public static void main(String[] args) {
    BCar bcar = new BCar();
    System.out.println(bcar.print());  //BCar를 출력.
}

-Dynamic Dispatch  : 정적 디스패치와 반대로 컴파일러가 어떤 메서드를 호출하는지 모르는 경우. 동적 디스패치는 호출할 메서드를 런타임 시점에서 결정.

→인터페이스나 추상 클래스에 정의된 추상 메소드를 호출하는 경우

→인터페이스 또는 추상클래스로 선언하고 구현/상속 받은 하위 클래스의 인스턴스를 생성.

→컴파일러가 알고 있는 타입에 대한 정보를 토대로 런타임 시 해당 타입의 객체를 생성하고 메서드를 호출.

public abstract class Job {
    abstract void printJob();
}
public class Student extends Job {
    @Override
    public void printJob() {
        System.out.println("Student");
    }
}
public class Teacher extends Job {
    @Override
    public void printJob() {
        System.out.println("Teacher");
    }
}
public class DynamicDispatch {
    public static void main(String[] args) {
        Job student = new Student();
        Job teacher = new Teacher();

        student.printJob();
        teacher.printJob();

→런타임 전에는 객체 생성이 되지 않기 때문에 컴파일시 어떤 클래스의 printJob인지 모름.

런타임에 메서드를 호출할 때 이 receiver parameter 를 보고 어떤 객체인지 판단 후 그 클래스의 메서드를 호출.

-Double Dispatch  : Dynamic Dispatch 를 두 번 하는 것을 의미.

→방문자 패턴 (Visitor Pattern) - 여러 객체에 대해 각 객체의 동작들을 지정하는 패턴 (N:N)

→일반적으로 OOP는 객체가 스스로 행위를 수행하게 하지만, 경우에 따라(ex. 확장성 고려, OCP 위배) 객체의 행위 수행을 외부 클래스에 위임. 이 때 사용하는 디자인패턴 종류는 전략패턴, 커맨드패턴, 방문자 패턴

→더블 디스패치는 방문자 패턴과 밀접한 관계.

5.추상 클래스


추상클래스란?

미완성 설계도. 추상메서드를 포함하는 클래스.

-추상클래스로 인스턴스 생성 불가

-추상클래스는 상속을 통해서 자손클래스에 의해서만 완성될 수 있음

(자손클래스에서 반드시 추상메서드를 구현해야함)

abstract class 클래스이름{}

abstract class Player{
	abstract void play(int pos); //추상메서드
	abstract void stop(); //추상메서드

class AudioPlayer extends Player{
	void Play(int pos) {/*...*/} // 추상메서드 구현
	void stop() {/*...*/} // 추상메서드 구현

-기존 클래스의 공통된 부분을 뽑아내서 조상클래스로 만드는 것

cf. 추상화 vs 구체화

→추상화: 클래스간의 공통점을 찾아내어 공통의 조상을 만드는 작업

→구체화: 상속을 통해 클래스를 구현, 확장하는 작업

6.final 키워드


final: 마지막의, 변경될 수 없는.

→클래스, 메서드, 멤버변수, 지역변수에 사용 가능

→ final + 변수 = 상수

final + 메서드 = 오버라이딩 x

final + 클래스 = 상속 x

cf. 제어자란?

클래스, 변수 또는 메서드의 선언부에 함께 사용되어 부가적인 의미 부여.

외부로부터 데이터 보호 및 외부에 불필요한 부분 감추기 위해 사용.

-접근제어자: public, protected, default, private

-그외: static, final, abstract, native, transient, synchronized, volatile, strictfp

→static: 클래스의, 공통적인. 클래스변수는 인스턴스에 관계없이 같은 값(하나의 변수를 모든 인스턴스가 공유)이며 클래스가 메모리에 로드될때 생성. static붙은 멤버변수, 메서드, 초기화 블럭은 인스턴스 사용하지 않고 사용 가능.

→abstract: 추상의, 미완의. 추상메서드는 메서드의 선언부만 작성하고 수행내용 구현x. 추상메서드가 선언된 클래스가 추상클래스. 추상클래스는 인스턴스 생성 불가.

7.Object 클래스


Object클래스란?

모든 클래스 상속계층도의 최상위에 있는 조상클래스.

다른 클래스로부터 상속받지 않는 모든 클래스는 자동적으로 object 클래스로부터 상속받음.

profile
우당탕탕 개발 일기

0개의 댓글