[JAVA] 상속(extends), 추상 클래스(abstract), 인터페이스(implements) 정리
상속(extends), 추상 클래스(abstract), 인터페이스(implement)
객체지향을 조금이라도 공부한 사람들은 상속, 추상 클래스, 인터페이스에 대해 계속적으로 들어봤을 것이다. 이 개념들이 객체 지향 프로그래밍을 하는데 중요한 개념이기 때문이다.
이것들은 어플리케이션을 설계하는데 공통된 부분을 묶어 정의해주고, 구조화 해주며, 객체로 활용할 수 있도록 도와준다.
이것들에 대한 개념 및 예제들은 많이 찾아볼 수 있으므로, 여기서는 간단히 정리하겠다.
1. 상속 (extends)
상속은 기존의 클래스로 부터 새로운 클래스를 유도하는 과정이다.
쉽게 말해서 부모 클래스를 extends로 상속받아 자식 클래스에서 내 것처럼 사용할 수 있는 것이다.
시스템을 설계하다보면, 공통된 부분으로 인하여 중복되는 것들이 계속적으로 나올 수 있다. 이럴때 상속을 이용하여, 비슷한 객체끼리 하나의 묶음으로 묶어주고, 공통된 부분을 뽑아서 상위 개념의 부모 클래스를 생성한다. 그리고 이 객체들이 부모 객체를 상속하면 중복이 제거되며, 공통된 방식으로 설계할 수 있다.
또한 오버로딩과 오버라이딩을 사용하여 자식 클래스에서 자유자재로 필요한 클래스를 구현할 수 있다.
상속을 사용하여 소프트웨어 재사용을 쉽게 할 수 있는 것이다.
- protected : 객체를 캡슐화하기 위해서 변수들의 modifier를 private로 설정하면, 이 객체를 상속받은 자식 클래스에서는 접근을 할 수가 없다. 외부에서의 변수에 접근은 막고 싶고, 자식 클래스에는 접근을 허용하고 싶을 때는 protected modifier를 사용하자. protected modifier는 외부에는 접근이 제한되고, 같은 패키지와 하위 클래스에만 접근을 허용한다.
- super 참조 : 예약어 super 는 그 부모 클래스를 참조하는데 사용한다. 생성자인 super() 를 호출하면, 부모 클래스의 생성자를 호출하게 된다. 상위 클래스의 생성자를 호출하는 super() 는 반드시 해당 클래스의 생성자 첫 번째 라인에 위치해야 한다. 이것은 상위 클래스의 생성자가 항상 하위 클래스의 생성자보다 먼저 수행되어야 하기 때문이다.
- 단일 상속 : 자바에서는 다중 상속을 지원하지 않는다. 따라서 extends 를 통해 하나의 부모만을 가질 수 있는 단일 상속만 사용할 수 있다.
- 오버라이딩(Overriding) : 상위 클래스의 메소드를 하위 클래스가 재정의해서 사용하는 기술이다. 하위 클래스에서 상위 클래스의 메소드 이름, 매겨변수 유형을 동일하게 정의하면 하위 클래스에서 해당 메소드를 재정의하게 된다.
- 상속의 제약 : 상수 final 을 선언하면, 다른 클래스에서 해당 클래스를 상속할 수 없다. final을 메소드에서 사용할 경우 하위 클래스에서 오버라이딩이 불가능하다. final 은 최종 클래스에서 사용 가능하며, 더이상 확장할 수 없다.
2. 추상 클래스 (abstract)
abstract는 추상 클래스를 선언할 때 사용하는 modifier이다.
클래스 선언부에 abstract를 사용하면 추상 클래스를 선언하고 있다는 의미이며, 메소드를 선언할 때 사용하면 추상 메소드를 만들고 있다는 의미이다.
추상 클래스는 추상적인 내용만 정의하고 있는 클래스로 구체적인 내용은 하위 클래스에서 구현되도록 해놓은 클래스이다. 추상 클래스가 반드시 추상 메소드를 가지고 있어야 된다는 제약이 있는 것은 아니지만 일반적으로 하나 이상의 추상 메소드를 가지고 있다.
추상 클래스를 상속하면(extends) 하위 클래스에서는 추상 클래스에 선언되어 있는 추상 메소드를 구현해야 한다. 어떤 면에서 추상 클래스는 인터페이스와 유사하다. 그러나 인터페이스와는 다르게, 추상 클래스는 추상 메소드가 아닌 메소드를 포함할 수도 있고 상수 이외의 데이터 선언도 포함할 수 있다.
추상 클래스의 자식 클래스는 부모로부터 상속받은 모든 추상 메소드들을 정의해야 한다. 그렇지 않으면 자식 역시 추상 클래스가 된다.
추상 메소드를 final 이나 static 으로 정의하는 것은 모순이라는 점을 주의해라. final 메소드는 자식 클래스에서 재정의 될 수 없다. static 메소드는 클래스 객체 선언 없이 클래스 이름으로 호출하는 이 방법은 그 메소드에 대한 구현이 이미 있어야만 가능하다. 추상 메소드는 구현이 없으므로 static 메소드는 말이 안된다.
어떤 클래스와 메소드를 추상으로 할 것인가는 설계 과정에 있어서 매우 중요한 부분이다.
3. 인터페이스(implements)
상속의 개념은 클래스뿐만 아니라, 인터페이스에도 적용될 수 있따. 즉 하나의 인터페이스는 다른 인터페이스로부터 파생될 수 있다는 것이다. 이러한 관계는 클래스 계층구조와 비슷하게 인터페이스 계층구조를 형성한다.
인터페이스는 다중상속을 지원하지 않는 자바에서 다중상속과 유사한 기능을 구현할 수 있게 한다.
인터페이스는 멤버변수와 메소드로 구성되는데 멤버변수는 모두 상수형으로 선언되고 메소드는 모두 추상 메소드로 선언된다.
인터페이스를 구현하고자 하는 클래스는 선언할 때 implements를 이용해서 인터페이스를 지정하고, 지정된 인터페이스가 가지고 있는 추상 메소드를 오버라이딩해야 한다.
클래스는 인터페이스 유형으로 변환될 수 있는데, 클래스가 구현하고 있는 인터페이스 유형으로만 변환할 수 있다.
클래스가 상속 관계에 따라 계층 구조를 가지듯이, 인터페이스도 인터페이스 사이의 상속 관계에 따라 계층 구조를 가질 수 있는데, 인터페이스의 경우는 클래스와는 다르게 여러 개의 인터페이스로부터 상속 받을 수 있다.
* 상속을 설계할 때 고려할 사항
(1) 모든 상속은 is-a 관계이어야 한다. 자식은 부모보다 더 구체적인 버전이어야 한다.
(2) 재사용과 미래의 재사용이 가능하도록 클래스 계층구조를 설계한다.
(3) 고려중인 도메인에서 클래스와 객체가 판별됨에 따라 그들의 공통점을 찾는다. 공통적인 기능들을 클래스 계층구조에서 일관성과 유지 용이성이 적절한 만큼 가능한 높이 위치시킨다.
(4) 메소드를 자식의 기능에 맞도록 적절하게 오버라이딩한다.
(5) 필요한 만큼 자식 클래스에 새로운 변수를 추가한다. 그러나 상속된 변수를 재정의 하지 않는다.
(6) 각 클래스가 자신의 데이터를 관리하도록 한다. 따라서 필요하다면 부모의 구성자를 호출하거나 오버라이딩 된 메소드를 호출하는 데 super를 사용한다.
(7) 여러 역할을 하는 클래스를 생성하는데(다중 상속이 필요할 때) 인터페이스들을 사용한다.
(8) 미래에도 유용할 수 있도록 응용의 요구에 부합하는 클래스 계층구조를 설계한다.
(9) 현재 사용하지 않더라도 toString 이나 equals 같은 일반적인 메소드들은 상속된 버전이 나중에 의도하지 않은 문제를 야기하지 않도록 자식 클래스에서 적절하게 재정의한다.
(10) 계층구조에서 하위에 있는 구체적 클래스들을 위하여 공통적인 클래스 인터페이스를 명시하는 데 추상 클래스를 사용한다
(11) 캡슐화를 위반하지 않고 파생 클래스에서 필요한 접근을 하도록 final 상수를 주의 깊게 사용한다.
출처: https://hyeonstorage.tistory.com/180?category=557602 [개발이 하고 싶어요]
'JAVA > Java' 카테고리의 다른 글
[JAVA] 예외 처리 Exception try-catch-finally, throws, 사용자 정의 예외 (0) | 2019.10.01 |
---|---|
[JAVA] 예외(Exception) 란? 체크예외와 RuntimeException (0) | 2019.09.30 |
[JAVA] 객체의 형 변환 (0) | 2019.09.30 |
[JAVA] 오버로딩(Overloading) 오버라이딩(Overriding) (0) | 2019.09.30 |
[JAVA] StringBuffer 클래스 정리 (0) | 2019.09.30 |
[JAVA] Object 클래스 정리 (0) | 2019.09.30 |
[JAVA] final, static, abstract, synchronized (0) | 2019.09.30 |
[JAVA] 접근제어자 public, protected, private (0) | 2019.09.30 |