Programming/Java

[Java] 다형성 (추상클래스 - 인터페이스)

kmindev 2023. 10. 16. 09:34

 

남궁성님의 Java의 정석(3rd Edition)을 보고 정리한 글입니다.

 

 

추상클래스와 인터페이스를 알아보기 전에 객체지향의 핵심 원리인 다형성에 대해서 정리해보자.

1. 다형성(polymorphism)이란?

  • 부모 타입의 참조변수로 자식타입의 객체를 다룰 수 있는 것
  • 자식타입의 참조변수로는 부모타입의 인스턴스를 참조할 수 없다.
  • 다형성을 사용하면 유지보수에 큰 이점을 가져올 수 있으면 객체지향의 핵심 원리이다.
public class Main {
    public static void main(String[] args) {
        Parent parent = new Child(); // => 다형성
        
        Child child = new Parent(); // 에러. 자식은 부모의 모든 멤버를 가지지만, 부모는 자식의 멤버를 모두 가지지 않는다 
    }
}

class Parent {
    int age;

    void parentMethod() {
        System.out.println("부모 클래스");
    }
}

class Child extends Parent {
    void ChildMethod() {
        System.out.println("자식 클래스");
    }
}

 

 

2. instanceof 연산자

  • 참조변수가 참조하는 인스턴스의 타입을 체크하는데 사용하는 연산자
  • 연산 결과는 true, false
  • 연산결과가 true이면 해당 타입으로 형변환이 가능
public class Main {
    public static void main(String[] args) {
        Parent parent = new Child();

        if(parent instanceof Parent) {
            System.out.println("parent는 Parent 타입입니다.");
        } else {
            System.out.println("parent는 Parent 타입이 아닙니다.");
        }

        if(parent instanceof Child) {
            System.out.println("parent는 Child 타입입니다.");
        } else {
            System.out.println("parent는 Child 타입이 아닙니다.");
        }
    }
}

class Parent {
   // ...
}

class Child extends Parent {
    // ...
}

실행결과
parent는 Parent 타입입니다.
parent는 Child 타입입니다.

 

3. 추상클래스(abstract class)란?

  • 미완성 설계도
  • 추상클래스는 하나 이상의 추상메서드를 포함하고 있는 클래스
  • 추상메서드는 선언만 하고 메서드 바디가 없는 메서드
abstract class Parent { // 추상 클래스
	int age;  // 필드

	void parentMethod() {  // 일반 메서드
		...
	}

	abstract void setAge();  // 추상 메서드
}

 

a. 추상클래스 예제

abstract class Parent { // 추상 클래스
    int age;  // 필드

    void parentMethod() {  // 일반 메서드
        // ...
    }

    abstract void setAge(int age);  // 추상 메서드
}

class Child extends Parent {
    void ChildMethod() {
        System.out.println("자식 클래스");
    }

    @Override
    void setAge(int age) {
        super.age = age;
    }
}


class Exam {
    public static void main(String[] args) {
        Parent parent = new Child(); // 다형성을 지원한다.
//        Parent parent = new Parent();  // 에러. 추상클래스는 인스턴스화를 금지한다.
    }
}
  • 다형성을 지원한다.
  • 추상클래스를 상속받는 자식클래스는 반드시 추상 메서드를 오버라이딩 해야한다.
  • 추상클래스는 인스턴스화를 금지한다.

 

 

 

4. 인터페이스(interface)란?

  • 추상 클래스보다 추상화 정도가 높다.
  • 실제 구현된 것이 전혀 없는 기본 설계도
  • 추상메서드와 상수만을 멤버로 가진다.
  • 인스턴스를 생성할 수 없다.
  • 자바에서는 인터페이스를 통해 다중 상속을 지원한다.

 

a. 인터페이스 예시

interface Lendable {
	public static final int a = 0; // public static final 생략 가능
	
	// public abstract 생략 가능
	public abstract void checkOut(String borrower, String date);
	public abstract void checkIn();
}

 

b. 인터페이스 상속

interface Moveable {
    void move(int x, int y);
}

interface Attackable {
    void attack(Object o);
}

interface Figtable extends Moveable, Attackable {
    void time(int t);
}
  • 인터페이스를 통해 다중 상속을 지원한다.
  • 인터페이스가 인터페이스를 상속받을 때 extends 키워드를 사용한다.

 

c. 인터페이스 구현

class people implements Figtable {

    @Override
    public void move(int x, int y) {
        // ...
    }

    @Override
    public void attack(Object o) {
        // ...
    }

    @Override
    public void time(int t) {
        // ...
    }
}

interface Moveable {
    void move(int x, int y);
}

interface Attackable {
    void attack(Object o);
}

interface Figtable extends Moveable, Attackable {
    void time(int t);
}
  • 클래스가 인터페이스를 상속받을 때 implements 키워드를 사용한다.
  • 모든 추상메서드를 오버라이딩 해야한다.

 

d. 인터페이스를 이용한 다형성

  • 클래스간의 상속관계와 마찬가지로 다형성을 지원한다.
public class Main {
    public static void main(String[] args) {
        MyInterface myInterface = new People();
        
        People people = new MyInterface(); // 에러

    }
}

class People implements MyInterface {
}

interface MyInterface {
}

 

e. Default 메서드

  • JDK1.8부터 추가되었다.
  • 인터페이스의 구현체(클래스)는 모든 메서드를 오버라이딩 해야했다.
  • Default 키워들 사용하면 필요할 때만 오버라이딩 해서 사용하면 된다.
  • 메서드 바디를 가지고 있다.
class People implements MyInterface {
    @Override
    public void method(int t) {
    	// ...
    }
    
    @Override
    public void newMethod() {
    	// ...
    }
}

interface MyInterface {
    void method(int t);
    default void newMethod(){}
}

 

f. 인터페이스 장점

  • 개발 시간 단축
    • 인터페이스를 사용하면 다른 개발자들이 각각의 부분을 완성할 때 까지 기다리지 않고 서로 규약만 정해두어 각자의 부분만 따로 나눠서 작성할 수 있다.
  • 표준화
    • 틀을 제공해주므로 정형화된 개발을 할 수 있다.
  • 서로 관계없는 클래스들에게 관계를 맺어줄 수 있다.
    • 아무런 관계가 없는 클래스들에게 인터페이스를 상속 받으므로 관계를 맺을 수 있다.
  • 독립적인 프로그래밍이 가능
    • 클래스간 결합도를 낮출 수 있고, 코드의 종속성을 줄이고 유지보수성을 높인다.