목표
자바의 상속에 대해 학습하세요.
학습할 것 (필수)
- 자바 상속의 특징
- super 키워드
- 메소드 오버라이딩
- 다이나믹 메소드 디스패치 (Dynamic Method Dispatch)
- 추상 클래스
- final 키워드
- Object 클래스
상속
상속이란 기존의 클래스에 기능을 추가하거나 재정의해 새로운 클래스를 정의하는 것을 의미한다.
말그대로 기존의 클래스에 정의되어있는 모든 필드와 메소드를 물려받고, 추가적인 필드와 메소드를 구현할 수 있도록 한다.
이 때, 기존에 정의된 클래스를 상위 클래스(Super Class)라고 하고 상위 클래스를 상속받는 클래스를 하위 클래스(Sub Class)라고 한다.
아래 다이어그램에서 Animal(동물)은 Mammal(포유류), Bird(조류), Reptile(파충류)의 상위 클래스이다.
public class Animal
{
public String name;
}
public class Mammal extends Animal
{
public boolean breastFeed;
}
public class Bird extends Animal
{
public int wings;
}
public class Reptile extends Animal
{
public boolean amnion;
}
상속이라는 단어로 인해 발생하는 오해가 있는데, 객체지향 언어에서 상속은 계층을 의미하는 것이 아니다.
객체지향 언어에서 상속은 확장을 의미한다. 때문에, 하위 클래스에서 상위 클래스를 상속할때 extends 키워드를 사용한다.
예를 들어, 상속이 계층을 의미한다면 아래와 같은 상황이 발생한다.
- 부모는 자식을 낳는다.
- 이를 계층으로 본다면, 부모는 상위 클래스 자식은 하위 클래스가 된다.
- 다시 이를 코드로 변경하면 자식이 부모 역할을 하게되는 이상한 일이 발생한다.
Parent child = new Child();
그렇다면 제대로된 상속을 구현하면 어떻게 변경해야할까?
- 부모-자식 간의 상속 관계를 끊는다.
- 자식(Child) 클래스의 하위 클래스로 아들(Son), 딸(Dauther) 클래스를 작성해 상속관계를 맺는다.
public class Parent
{
public List<Child> children = new ArrayList();
public void addChild(Child child)
{
this.children.add(child);
}
}
public class Child
{
public string name;
public Child(String name)
{
this.name = name;
}
}
public class Son extends Child
{
public Son (String name)
{
super(name);
}
}
public class Dauther extends Child
{
public Dauther (String name)
{
super(name);
}
}
Parent parent = new Parent(); // 부모
Child son = new Son(); // 아들
Child dauther = new Dauther(); // 딸
parent.addChild(son);
parent.addChild(dauther);
Java 상속의 특징
- 다중상속이 불가능하다.
- 모든 클래스는 Object 클래스의 하위 클래스이다.
- 상속의 횟수는 제한이 없다.
- 상위 클래스에서 변수 또는 메소드의 접근 제한자를 private로 지정한 경우, 변수는 상속받으나 접근할 수 없고 메소드는 상속받지 않는다.
super
super 키워드는 하위 클래스에서 상위 클래스에 접근할 수 있도록 해준다.
위 코드 중 Son 클래스의 경우, 아래와 같이 super 키워드를 이용해 상위 클래스의 변수 name에 접근할 수 있다.
public class Son extends Child
{
public void sayMyName()
{
System.out.println("My name is " + super.name);
}
}
그리고 super() 호출 시, 상위 클래스의 생성자 메서드를 호출할 수 있다.
메소드 오버라이딩
메소드 오버라이딩은 하위 클래스에서 상위 클래스에 존재하는 메소드를 재정의해 사용하는것을 의미한다.
하위 클래스에서 상위 클래스를 상속받으면 하위 클래스 객체에서 상위 클래스에서 작성된 메소드를 호출할 수 있는데, 만약 해당 메소드의 로직이 해당 클래스에서는 달라야할 경우 사용할 수 있다.
단, 오버라이딩은 기능의 재정의이므로 아래와 같은 제약이 있다.
- 메소드 선언부는 상위 클래스와 동일해야한다.
- 상위 클래스보다 좁은 범위의 접근 제한자를 사용할 수 없다.
- 상위 클래스보다 더 넓은 범위의 예외를 선언할 수 없다.
메소드 오버라이딩을 하면 @Override 어노테이션을 메소드 선언부 상단에 작성하는데, 작성하지 않아도 오류가 발생하지는 않지만 컴파일시에 오버라이딩이 정상적인지 검증해주기 때문에 @Override 어노테이션을 작성하는 것을 권장한다.
다이나믹 메소드 디스패치
디스패치는 프로그램이 어떤 메소드를 호출할 것인지를 결정해 실행하는 과정을 의미하며, 2가지 종류가 있다.
- Static Dispatch : 구현 클래스를 이용해 컴파일 시점에서부터 어떤 메소드가 호출될 지 결정
- Dynamic Dispatch : 추상 클래스나 인터페이스를 참조함으로써 호출되는 메소드가 동적으로 결정
/**
* Static Dispatch 예시코드
*/
public class Main
{
public static void main(String[] agrs)
{
StaticDispatch sd = new StaticDispatch();
sd.echo();
}
}
public class StaticDispatch
{
public void echo()
{
System.out.println("StaticDispatch");
}
}
/**
* Dynamic Dispatch 예시코드
*/
public class Main
{
public static void main(String[] agrs)
{
DynamicDispatch sd = new DynamicDispatchImpl();
sd.echo();
}
}
interface DynamicDispatch
{
void echo();
}
public class DynamicDispatchImpl implements DynamicDispatch
{
public void echo()
{
System.out.println("DynamicDispatchImpl");
}
}
추상 클래스
추상 클래스(Abstract Class)는 미완성된 설계도라고 비유할 수 있다. 미완성된 설계도로 완성된 제품을 만들 수 없듯이 추상 클래스로는 인스턴스를 생성할 수 없으며, 상속을 통한 하위 클래스에서의 인스턴스화로 완성될 수 있다.
추상 클래스는 반드시 하나 이상의 추상 메서드를 가지고 있어야하고, 이 추상 메서드를 하위 클래스에서 오버라이드 해야한다.
// 추상 클래스
abstract class 클래스명
{
// 추상 메서드
abstract 접근제한자 리턴타입 메서드명(매개변수);
}
추상 메서드는 보통의 메서드와는 달리 구현부가 없다. 추상 메서드는 선언부만 작성하며, 주석으로 해당 메서드에 대한 목적 등을 작성해 하위 클래스에서 해당 목적에 맞게 구현하도록 유도한다. 하위 클래스에서는 이 추상 메서드들을 모두 구현해야만 한다.
만약, 추상 클래스를 상속받는 하위 클래스에서 구현하지 않는 경우 해당 하위 클래스 또한 추상 클래스로 지정해야한다.
final
final은 자바 예약어로 변수, 메서드, 클래스 앞에 붙으면 해당 변수, 메서드, 클래스는 변경할 수 없는 상태가 된다.
final을 사용하지 않더라도 로직상에서 값을 변경하지 않으면 동일한 결과가 나오지만, final을 사용하면 명시적이면서 강제적으로 불변의 값이 되기 때문에 불변의 값에는 반드시 사용하도록 한다.
- 변수 : final 키워드가 붙은 멤버 변수는 선언과 동시에 값을 할당하거나, 생성자를 통해 값을 할당할 수 있다.
- 메서드 : final 키워드가 붙은 메서드는 해당 클래스를 상속받는 하위 클래스에서 해당 메서드를 오버라이드 할 수 없다.
- 클래스 : final 키워드가 붙은 클래스는 어떠한 클래스도 해당 클래스를 상속받을 수 없다.
Object 클래스
java.lang 패키지는 자바 프로그램 내에서 import 하지 않아도 자동으로 포함 되는 패키지이다.
그중 Object 클래스는 모든 자바 API와 사용자가 작성한 모든 클래스의 최상위 클래스이다.
즉, 모든 클래스는 Object 클래스를 상속받으며 클래스 선언부에서 extends Object를 명시하지 않더라도 자동으로 상속받는다.
때문에 Object 클래스의 모든 메서드와 변수는 모든 클래스에서 동일하게 사용할 수 있다.
이미지 출처 : java.lang 패키지 구조 (web.deu.edu.tr/doc/oreily/java/langref/ch10_js.htm)
'☕️ JAVA > WhiteShip Java LIVE Study' 카테고리의 다른 글
[WhiteShip Java LIVE Study] 5주차 : 클래스 (1) | 2020.12.25 |
---|---|
[WhiteShip Java LIVE Study] 4주차 : 제어문 (0) | 2020.12.11 |
[WhiteShip Java LIVE Study] 3주차 : 연산자 (0) | 2020.11.30 |
[WhiteShip Java LIVE Study] 2주차 : 자바 데이터 타입, 변수 그리고 배열 (0) | 2020.11.20 |
[WhiteShip Java LIVE Study] 1주차 : JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가 (0) | 2020.11.15 |