공부/Java

일단 마시고 본다. (상속)

오잎 클로버 2022. 4. 25. 09:00
728x90

자바를 개발하다 보면 상속이라는 개념을 배우게 됩니다.

그리곤 extends Object 가 있다는 것만 기억하게 되고 상속을 잊어버립니다.

(전부가 그렇다는 것은 아니지만 제 친구는 잊어버렸습니다.

실제로 추상클래스 상속하라고 했더니 클래스 상속 어떻게 하는 건데? 인터페이스여야지만 상속되는 거 아니었음? 라고 했던 비하인드가 있습니다.(그친구는 개발에 흥미만 있는 친구입니다.))

 

상속은 자바에 있어 굉장히 중요한 개념입니다.

부모가 가진 것을 자식에게 물려줄 수 있다는 점, 그리고 protected로 부모와 자식외에는 접근조차 불가한 접근 제어자까지 있습니다. 또, 부모에서 받은 것들을 재정의할 수 있다는 점에서 더 중요함을 알려줍니다.

 

예시를 들자면, Machine과 Robot으로 간단하게 들 수 있습니다.

Robot은 로봇으로 Machine(기계)를 상속합니다.

당연하게도 로봇 이전에는 기계가 있었고, 기계를 기본적인 형태를 응용하여 만든 것이 로봇이니 말이죠

public class Machine {
    public void powerOn() {
    	System.out.println("전원 킴");
    }
    
    public void powerOff() {
    	System.out.println("전원 끔");
    }
}
public class Robot extends Machine {
    public void action() {
    	System.out.println("작동");
    }
}

여기서 자바의 상속은 현실세계에서의 상속과는 차이가 많이 크다는 것을 알 수 있습니다.

우선, 상속자가 누구인지를 부모클래스는 알지 못합니다. 그냥 공유자원으로 사용되고 맙니다.

둘, 상속자가 부모를 상속할 수 있는 권한을 가집니다. 부모의 가장 가까운 사람이 순차적으로 상속자가 되는 현실과 다르게 자바에서는 상속자가 부모를 택할 수 있습니다.

셋, 상속을 받아서 재정의를 할 지 하지 않을 지 부모단에서 강요하지 않는 한 이는 선택입니다.

(현실에서는 부모단에서 강요를 한다고 하여 법에 의해 반드시 상속을 받아야한다는 법이 없기 때문에 현실과 다릅니다.)

 

또다른 예시를 들어봅시다.

만일 Robot과 Human 클래스를 상속하는 Cyborg(사이보그) 클래스를 만든다고 가정해봅시다.

그렇다면 코드는 다음과 같이 구성할 수 있습니다.

(Human 클래스는 이미 구현되어있다고 가정합니다.)

public class Cyborg extends Robot, Human {
    public void eat(String food) {
    	System.out.printf("%s를 먹습니다.\n", food);
    }
}

위와 같이 개발하면 참 좋을 것 같지만, 안타깝게도 자바의 상속은 현실과 다른 것은 위 세가지 뿐이 아니었습니다.

넷, 다중 상속이 불가하다.

다중 상속이 불가능한 이유는 다음과 같습니다.

출처: 위키피디아. 다중상속

D가 부모클래스이고, B, C는 D를 부모로 둔 자식 클래스이고, B, C를 부모로 둔 A클래스가 이 둘을 전부 가지게 된다면

어떤 메소드가 누구의 메소드인지, 어떤 변수가 누구의 변수인지를 가늠할 수 없기때문입니다.

물론 인터페이스에서는 허용해주지만 이는 추후 작성할 인터페이스에서 참고해주세요.

 

자기 자신을 가르키는 키워드는 자바를 하신 분들은 다들 아시듯, this입니다.

그렇다면 부모를 가르키는 키워드는 무엇일까요? 바로 super입니다.

super를 사용하여 부모의 생성자뿐 아닌 부모가 구현해놓은 메소드를 직접 호출할 수 있습니다.

 

 

클래스를 생성하게 되면 기본적으로 Object를 자동으로 상속하게 됩니다.

그렇기에 사용할 수 있는 메소드가 몇가지 있습니다.

  • super
  • hashCode
  • equals
  • finalize
  • toString
  • clone

이 들은 추후 자세히 다루도록 하겠습니다.

 

이 상속을 사용하여 인터페이스와 일반 클래스 그 가운데 위치한 추상클래스를 만들 수 있습니다.

public abstract class Bird {

    public abstract void sing();

    public void fly() {
        System.out.println("날다.");
    }

}
public class Duck extends Bird {

    @Override
    public void sing() {
        System.out.println("꽥꽥!!");
    }
}
public class BirdExam {

    public static void main(String[] args) {
        Bird bird = new Bird(); // 불가
        Duck duck = new Duck();
        duck.sing();
        duck.fly();
    }

}

새 라는 추상 클래스를 생성하고 이를 상속하여 sing이라는 메소드는 추상 메소드로 자식 클래스에게 생성을 강요합니다.

그리고 오리라는 클래스는 새 추상 클래스를 상속하여 sing이라는 메소드를 재정의를 통해 구현했습니다.

추상 클래스는 구체적이지않는 클래스라는 뜻인만큼 일반적인 방법으로는 생성자 호출이 불가능합니다.

물론 다음과같은 방법으로 생성자 호출이 가능하긴 합니다.

Bird bird = new Bird() {
    @Override
    public void sing() {
        System.out.println("짹짹");
    }
};

 

 

(몇가지 내용들을 생략 및 불친절하나, 부족한 내용들은 노션 페이지로 표시해두었습니다. 참고해주세요.)

https://cns-java.notion.site/fc72aced5a0e42ffa48423946d0026ce

이상입니다.