Search
Duplicate

Java - 추상 클래스(abstract class)와 인터페이스(interface)

글감
Java
작성자
작성 일자
2024/02/08 06:43
상태
완료
공개여부
공개
Date
생성자
작업자

추상 메서드(abstract method)

추상 메서드는 자식 클래스에서 반드시 오버라이딩해야만 사용할 수 있는 메서드로, 자바에서 추상 메서드를 선언하면 해당 메서드를 포함하는 클래스를 상속받는 자식 클래스가 반드시 해당 추상 메서드를 구현하도록 하기 위함이다.
모듈처럼 중복되는 부분이나 공통적인 부분들은 미리 만들어진 것을 사용하고, 이를 받아서 사용하는 쪽에서 필요한 부분만 재정의하여 사용함으로써 생산성을 높이고 배포를 쉽게하기 위해서 사용된다.
이런 특성상 추상 메서드는 선언부만 존재하며, 구현부는 작성되면 안된다.
abstract void abstractMethod();
Java
복사

추상 클래스(abstract class)

자바에서 하나 이상의 추상 메서드를 포함하는 클래스를 추상 클래스라고 부르며, 다형성을 가지는 메서드 집합을 정의할 수 있도록 해준다.
반드시 사용되어야 하는 메서드를 추상 메서드로 선언해 놓아서, 해당 클래스를 상속받는 모든 클래스에서 이 추상 메서드를 반드시 재정의해 사용하도록 만들 수 있다.
abstract class abstractClass { ... abstract void abstractMethod(); ... }
Java
복사
추상 클래스는 정의되지 않은 추상 메서드를 포함하고 있기 때문에, 자기 자신의 인스턴스를 생성할 수 없다. 상속을 통해 자식 클래스를 만들고, 자식 클래스에서 모든 추상 메서드를 오버라이딩하고 나서야 자식 클래스의 인스턴스를 생성할 수 있다.
abstract class Animal { abstract void cry(); } class Cat extends Animal { void cry() { System.out.println("냐옹냐옹!"); } } class Dog extends Animal { void cry() { System.out.println("멍멍!"); } } public class Polymorphism02 { public static void main(String[] args) { // Animal a = new Animal(); // 추상 클래스는 인스턴스를 생성할 수 없음. Cat c = new Cat(); Dog d = new Dog(); c.cry(); d.cry(); } }
Java
복사
자바에서 추상 메서드를 선언하여 사용하는 목적은 상속 받는 클래스에서 반드시 해당 메서드를 구현하도록 하기 위해 사용된다. 만약 이를 일반 메서드로 구현한다면, 자식 클래스에서는 구현을 할 수도 있고 안 할 수도있다.

인터페이스란

자식 클래스가 여러 부모 클래스를 상속받아 사용할 수 있다면, 다양한 동작을 수행할 수 있다는 장점을 가질 수 있다. 다중 상속을 할 경우 메서드 출처의 모호성 등 여러 문제로 인해, 자바에서는 클래스를 통한 다중 상속을 허용하지 않는다.
자바에서 이러한 이점을 사용하고 싶으면 인터페이스를 통해 다중 상속을 받아 사용하면 된다. 인터페이스란 다른 클래스를 작성할 때 기본 틀을 제공하며 다른 클래스 사이의 중간 매개 역할까지 담당하는 일종의 추상 클래스이다.
자바에서 추상 클래스는 추상 메서드와 생성자, 필드, 일반 메서드를 포함할 수 있지만, 인터페이스에서는 오직 추상 메서드와 상수만 포함할 수 있다.

인터페이스의 선언

인터페이스는 interface 키워드를 접근 제어자와 함께 사용하여 선언할 수 있다.
private interface Shape { public static final origin = 0; ... public abstract int getArea(int width, int height); ... }
Java
복사
인터페이스에서는 클래스와 달리 모든 필드를 public static final로 선언해야하며, 모든 메서드를 public abstract로 선언해야한다.

인터페이스의 구현

인터페이스는 추상 클래스와 마찬가지로 자신이 직접 인스턴스를 생성할 수 없고, 아래처럼 인터페이스를 구현하는 구현 클래스를 작성해야한다.
class Square implements Shape { ... public int getArea(int width, int height) { return width * height; } }
Java
복사
구현 클래스는 인터페이스의 모든 추상 메서드를 구현해야하고, 추상 메서드를 구현하지 않으려면 abstract 키워드를 사용하여 추상 클래스로 선언해야한다.
interface Animal { public abstract void cry(); } class Cat implements Animal { public void cry() { System.out.println("냐옹냐옹!"); } } class Dog implements Animal { public void cry() { System.out.println("멍멍!"); } } public class Polymorphism03 { public static void main(String[] args) { Cat c = new Cat(); Dog d = new Dog(); c.cry(); // "냐옹냐옹!" d.cry(); // "멍멍!" } }
Java
복사

인터페이스를 활용한 다중 상속

interface Animal { public abstract void cry(); } interface Pet { public abstract void play(); } class Cat implements Animal, Pet { public void cry() { System.out.println("냐옹냐옹!"); } public void play() { System.out.println("쥐 잡기 놀이하자~!"); } } class Dog implements Animal, Pet { public void cry() { System.out.println("멍멍!"); } public void play() { System.out.println("산책가자~!"); } } public class Polymorphism04 { public static void main(String[] args) { Cat c = new Cat(); Dog d = new Dog(); c.cry(); // 냐옹냐옹! c.play(); // 나비야~ 쥐 잡기 놀이하자~! d.cry(); // 멍멍! d.play(); // 바둑아~ 산책가자~! } }
Java
복사
이처럼 두 개 이상의 인터페이스를 다중 상속하여 구현 클래스를 작성할 수 있다.

인터페이스의 장점

다중 상속을 받는 클래스를 구현할 수 있다.
일관되고 정형화된 개발을 위한 표준화가 가능하여 대규모 프로젝트 개발 시 효율적으로 작업할 수 있다.
클래스의 작성과 인터페이스의 구현을 동시에 진행할 수 있어 개발 시간을 단축할 수 있다.
클래스와 클래스 간의 관계를 인터페이스로 연결하면, 클래스마다 독립적인 프로그래밍이 가능해진다.

디폴트 메서드(default method)

Java 8부터는 인터페이스에도 디폴트 메서드를 제공하여 인스턴스 메서드를 구현 형태로 제공할 수 있게 되었다.
public interface Vehicle { default void print() { System.out.println("I am a vehicle!"); } }
Java
복사
이런 디폴트 메서드의 사용 방법은 3가지가 있다.
구현 없이 인터페이스의 디폴트 메서드를 그대로 사용하는 방법
디폴트 메서드를 override하는 방법
인터페이스를 상속 받은 후 디폴트 메서드를 추상 메서드로 만들어 추상 클래스를 생성하는 방법
인터페이스에 디폴트 메서드를 추가하면, 다중 상속할 때 메서드의 이름이 같을 때 다음과 같이 모호함 문제가 발생한다.
public interface Vehicle { default void print() { System.out.println("I am a vehicle!"); } } public interface FourWheeler { default void print() { System.out.println("I am a four wheeler!"); } } public class Car implements Vehicle, FourWheeler { }
Java
복사
// error 메세지 Duplicate default methods named print with the parameters () and () are inherited from the types Vehicle and FourWheeler
Java
복사
이와 같은 모호함 문제를 해결하기 위해서는 2가지 방법이 있다.
구현 메서드를 통해 override 하는 방법
public class Car implements Vehicle, FourWheeler { public void print() { System.out.println("I am a four wheeler car vehicle!"); } }
Java
복사
사용할 부모 인터페이스를 지정하여 사용하는 방법
public class Car implements Vehicle, FourWheeler { public void print() { Vehicle.super.print(); } }
Java
복사