[Java] 상속
java에서 제공해주는 api 들이 보통 상속관계로 이루어져 있어서 상속을 확실히 이해를 해야 이러한 api를 잘 쓸 수 있다.
💡 수평적 설계 vs 수직적 설계
🔍 1. 상속 ➡ 클래스의 설계 (행위적인 측면)
기존에 사용했던 class 를 만들고 객체를 만드는 과정은 누군가에게 상속관계가 없는 수평적인 관계에 대해서 만들어 왔다.
기존의 수평적 코드의 특징을 살펴보면
➡ 코드의 중복이 발생
공통된 부분을 갖은 여러개의 클래스들이 중복되어 선언해야한다.
➡ 새로운 요구사항에 대한 코드의 수정 불가피
중복되는 부분의 특징이 변경되면 모든 클래스 마다 수정해야하는 번거로움이 있다.
➡ 관리하기가 어렵다.
dog 와 cat 클래스가 공통으로 가지고 있던 이름, 나이 , eat() 등의 특징을 Animal 이라는 부모가 갖고
dog와 cat 클래스는 해당 공통된 특징을 상속받아서 사용한다.
➡ 수평적 설계의 단점을 극복 할 수 있다.
1년이 지나 나이를 수정해야한다고 하면 dog cat 각각 수정해야 하는 부분을 animal 만 수정하면 모두 수정된다.
➡ 확장을 쉽게 할 수 있다.
다른 animal 관련 특징을 가진 사자 하마 비둘기 등등 클래스들을 쉽게 확장할 수 있다.
➡ 코드가 복잡해지지만 이점이 많다.
자식 객체에서 부모 객체로 갈 수록 "추상화, 보편화, 일반화, 개념화" 되고
부모객체에서 자식 객체로 갈 수록 "세분화, 상세화, 구체화, 구상화" 된다.
💡 2. 상속 개념
Animal 이라는 클래스에게 상속 받은 Dog 와 Cat을 살펴보자
name, age, part 라는 멤버변수와 eat 이라는 메서드를 가지고 있는 Animal 을
상속 받은 두 객체에는 같은 변수를 가지고 있을 것이다.
이것이 어떻게 가능한지 살펴보면
각 클래스마다 생성자 객체가 있는데
이 생성자 객체 내부에는 super(); 이라는 상속받는 메소드가 생략 되어 있다.
spuer() : 자신의 생성자에서 부모의 생성자를 먼저 호출한다.
이를 통해 객체를 선언하면 가장 먼저 extends 한 부모 클래스의 생성자 클래스를 호출한다.
그리고 나서 본인의 생성자 객체를 실행시킨다.
그렇다면 부모인 Animal이나 extends 를 쓰지 않은 클래스인 경우에는 상속을 안받을까???
아니다. Object 라는 모든 클래스의 부모 클래스가 존재한다.(최상위 클래스(Root)
모든 클래스들은 Object를 상속받는다.
그러면 위에서 super을 통해서 부모 생성자 클래스를 먼저 불러오게 된다고 했다.
그러면 어떠한 클래스를 통해서 객체를 생성하게 되면
Dog 클래스를 생성하면 super을 통해 부모 클래스은 Animal 생성자 클래스를 호출하고
Animal 클래스는 super을 통해 Object 클래스를 호출할 것이다.
이러한 상속을 거쳐서 메모리에 생성된 객체의 모양을 보면
이러한 방식 즉 상속체이닝 방식으로 생성되었다고 볼 수 있다.
💡 3. 상속이 왜 필요한지 살펴보기
우선 상속이 어떨때 주로 쓰이는지 살펴보자
일단 우리는 .java 파일과 .class 파일의 차이를 JVM 동작 방법을 통해 배웠다
사람이 만든 코드 파일이 .java 파일이며
컴파일러가 소스코드(.java)를 기계가 쉽게 이용할 수 있는 bytecode로 이루어진 .class 파일로 변환한다.
우리는 티비 기능의 코드를 팔고 있고 가정해보자.
내부에는 tv ON 메소드, VOLUME 메소드, 밝기 메소드 등등 다양한 메소드가 있는것을 만든 제작자는 잘 알고 있다.
하지만 이를 구매하려는 사람은 소스코드를 직접 보지 못하면 내부에 어떤 기능이 있는지 알기 어렵다.
그래서 소스코드를 요구할 것이다. 하지만 판매자 입장에서 엄청난 투자금을 들여 만든 소스코드를 주는건 말이 안된다.
즉 판매자는 기능이 동작하는 .class 파일 만을 팔기를 원하고
구매자는 어떤 기능이 있는지 파악이 가능한 .java (소스코드) 파일을 원한다.
여기서 대안이 해당 기능이 동작하는 도구를 함께 파는 것이다. 즉 내부의 기능을 보고 쓸 수 있는 리모컨을 파는것이다.
이 역할을 부모 객체가 상속을 통해서 해 줄 수 있다.
클래스의 세부 기능을 모두 사용하면서 핵심 소스코드 파일은 공유하지 않는 방법을 위해
부모클래스와 함께 상속한 코드를 배포한다.
💡 4. 코드로 살펴보기
예를 들어 dog 와 cat 의 클래스가 있다
dog에 있는 eat() 메소드는
개처럼 먹다 를 출력한다
cat에 있는 eat() 메소드는
고양이처럼 먹다를 출력한다.
이때 Animal 이라는 부모클래스를 만들어서 공통부분인 eat 을 가져 왔을때
여기서 eat() 메소드는 동물처럼 먹다 라는 정도로 표현이 가능하다.
그전의 eat() 메소드보다 포괄적이며 , 추상적으로 바뀌었다.
상속을 배울때 가장 중요한것은!
Animal 클래스로 dog.클래스와 cat.클래스를 동작 시킬 수 있는 방법을 배우는 게 핵심이다.
Dog 생성자 자체로 객체를 생성하는 것이 아니라
Animal 이라는 클래스를 통해서 Dog를 생성해서 Dog를 이용해준다.
상속에서 알아두어야 할 점은
자식 클래스가 부모 클래스의 기능을 포함하는 것이 아니다!!
자식 클래스가 부모 클래스의 기능을 사용할 수 있는 것이다.
메모리 관계에서 생각해야 한다.
cat 의 객체를 생성하면 생성자 메소드의 super 메소드에 의해서 상속받은 부모객체가 호출되고 메모리 위에 쌓인다.
이때 상속을 받은 cat은
원래 cat 만큼의 기능을 이용할 수 있었따면 상속을 통해
Animal 부분까지 이용이 가능한 것이다.(확장 extends)
Java 관련 개념을 알려주실 때 그 내부 동작이 어떻게 구현되는지 자세하게 알수 있는 강의입니다.
출처: Java TPC (생각하고, 표현하고, 코딩하고) 대시보드 - 인프런 | 강의 (inflearn.com)