Search
moon
sun

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
복사