추상 클래스와 추상 메서드
다형성을 위해 메서드의 선언은 통일해야 하지만, 실제로 구현하는 내용은 자식 클래스마다 달라야 할 때, 부모 클래스의 메서드는 비워두고 자식 클래스에서 오버라이딩하여 구현해낼 수 있다. 자바는 이와 같은 경우를 공식 지원하면 방법을 제공하고 있다. 우리는 선언부만 작성하고 구현부는 작성하지 않고 남겨둔 미완성 메서드를 '추상 메서드'라고 부른다. 추상 메서드를 선언할 때는 abstract 키워드를 함께 표기해야 한다. 또한 메서드 구현부인 중괄호{} 대신 구현부가 없다는 의미로 선언부 끝에 세미콜론(;)을 사용한다.
[접근제한자] abstract 반환 타입 메서드 이름 (매개변수1, 매개변수2, ...);
추상 메서드를 1개 이상 선언하면, 그 클래스는 추상 클래스로 선언해야 한다.
자바에서는 하나 이상의 추상 메서드를 포함하는 클래스를 가리켜 추상 클래스라고 한다. 추상 클래스는 추상 메서드를 포함하고 있다는 것을 제외하고는 일반 클래스와 다르지 않다. 추상 클래스에도 생성자가 있으며, 멤버변수와 메서드도 가질 수 있다.
[접근 제한자] abstract class 클래스 이름 {
// 필드
// 생성자
// 메서드 (추상 메서드 포함)
}
추상 클래스로 선언되는 클래스는 다음과 같은 제약 조건을 가진다.
- 일반 클래스처럼 독립적으로 생성자를 호출해 객체를 생성할 수 없다.
- 자식 클래스의 생성자에서 super()를 통해 추상 클래스의 생성자를 호출하여 부모 객체를 생성한 후 자식 객체를 생성한다.
자식 클래스 간의 공통적인 플드와 메서드 이름을 통일할 수 있다.
반드시 구현해야 하는 메서드를 선언함으로써 공통 규격을 제공한다.
자식 클래스들의 규격과 내용을 통일하기 위함이며, 이는 곧 객체 지향 프로그래밍의 다형성을 구현하기 위한 탄탄한 기반이 될 것이다. 실무에서는 이러한 용도가 업무 효율성에 큰 영향을 미친다. 간단하게는 같은 클래스를 상속받는 자식 클래스들을 각각 다른 개발자들이 구현한다고 가정할 때, 공통된 규격을 제공하고 반드시 구현해야 하는 메서드를 알게 함으로써 보다 통일감 있는 코드를 완성할 수 있다.
인터페이스 구현
모든 메서드가 추상 메서드인 일종의 추상 클래스를 우리는 '인터페이스'라고 부른다. 인터페이스는 추상 메서드와 상수로만 이루어져 있고, 추상 클래스와 마찬가지로 스스로 객체를 생성할 수 없다.
추상 클래스 : 클래스의 공통 메서드를 추출해 선언하며, 자식 클래스들이 상속받아 구현하도록 한다.
인터페이스 : 구현 클래스들의 기본 틀을 제공하면서, 다른 클래스 코드들과의 사이에서 중간 매개 역할을 한다.
인터페이스는 객체의 매개체, 즉 객체를 사용하는 방법을 제공하는 새로운 블록이라고 할 수 있다. 인터페이스를 선언할 때는 interface 키워드를 함께 사용하며, 다음과 같이 선언한다.
[접근 제한자] interface 인터페이스이름 {
...
접근 제한자 abstract 메서드이름(매개변수1, 매개변수2, ...)
...
}
인터페이스를 선언하는 방법은 클래스를 작성하는 방법과 동일하며 class 키워드 대신 interface를 작성한다. 또한 인터페이스의 추상 메서드는 다른 클래스들과의 매개체 역할을 하므로 누구나 접근할 수 있어야 한다. 따라서 항상 public으로 구현한다. 만약 접근 제한자를 default로 구현했다면 자동으로 public으로 인식할 것이다. 클래스와 달리 인터페이스의 모든 필드는 public / static / final 이어야 하며, 모든 메서드는 public / abstract 이어야 한다.
인터페이스 사용
추상 클래스는 추상 메서드가 비어있기 때문에 객체 생성을 스스로 할 수 없다. 대신 자식 클래스의 생성자의 힘을 빌려 객체 생성을 할 수 있다. 추상 클래스와 마찬가지로, 인터페이스 역시 추상 메서드가 비어있기 때문에 객체 생성을 스스로 할 수 없다. 따라서 인터페이스도 자신이 가지고 있는 추상 메서드를 구현해줄 클래스를 작성해야 하는데 이를 '구현 클래스'라고 한다.
구현 클래스는 인터페이스를 사용해 구현하겠다는 선언을 해야 한다. 구현한다는 의미를 가지고 있는 implements 키워드를 사용해 명시할 수 있다.
[접근 제한자] class 클래스이름 implements 인터페이스이름 {
// 필드
// 생성자
// 구현 메서드 (추상 메서드 오버라이딩)
}
인터페이스의 모든 추상 메서드를 오버라이딩하지 않으면 에러가 발생한다. 즉, 인터페이스를 구현하려면 모든 추상 메서드를 구현해야 한다. 만약 추상 메서드를 오버라이딩한 메서드의 접근 제한자를 public으로 지정하지 않으면 에러가 발생하기 때문에 반드시 public으로 지정해야 한다. 인터페이스의 상수를 가져와 사용하려면 인터페이스이름.상수 이름 과 같이 호출해야 한다.
인터페이스 상속
인터페이스끼리 상속 관계를 만들 수 있다. 클래스의 상속과 마찬가지로 extends 키워드를 사용하며, 다중 상속이 가능하기 때문에 콤마(,)를 이용해서 다음과 같이 선언한다.
[접근 제한자] interface 인터페이스이름 extends 인터페이스1, 인터페이스2, ...{
...
// 추상 메서드
}
클래스의 상속과 마찬가지로 인터페이스 상속을 선언하면, 하위 클래스는 상위 클래스의 모든 멤버를 상속받게 된다. 따라서 만약 하위 인터페이스를 구현하는 클래스가 있다면, 해당 클래스는 하위 인터페이스의 추상 메서드를 포함하여 상위 인터페이스의 추상 메서드까지 구현해야 한다.
'BOOK' 카테고리의 다른 글
| [JAVA] MENTOR JAVA SECTION 14 (1) | 2025.01.21 |
|---|---|
| [JAVA] MENTOR JAVA SECTION 13 (2) | 2025.01.20 |
| [JAVA] MENTOR JAVA SECTION 11 (2) | 2025.01.18 |
| [JAVA] MENTOR JAVA SECTION 10 (2) | 2025.01.17 |
| [JAVA] MENTOR JAVA SECTION 9 (1) | 2025.01.16 |