본문 바로가기
Java/Java

인터페이스와 다형성

by curious week 2025. 3. 18.

인터페이스와 다형성

추상 클래스 abstract 포함, 객체 생성 불가, 상속 필수
인터페이스 100% 추상, implements 필요, 다중 상속 가능
다형성 부모 타입 = 자식 객체 참조 가능
열거형 (Enum) 미리 정의된 상수값 집합
익명 클래스 1회성 클래스
중첩 클래스 내부 클래스, static / non-static

1. 추상 메소드

  • abstract 키워드를 사용
  • 몸체 없이 형식만 존재 (반환형, 이름, 매개변수 목록만 선언)
  • 자식 클래스가 반드시 구현
  • final과 함께 사용할 수 없음
  • 추상 클래스 또는 인터페이스에서 선언

예제

abstract class Animal {
    abstract void sound(); // 추상 메서드
}

class Dog extends Animal {
    void sound() { System.out.println("멍멍"); } // 구현 필수
}

2. 추상 클래스

  • abstract 키워드 사용
  • 추상 메서드를 포함할 수 있음
  • 객체 생성 불가 (불완전한 클래스)
  • 일반 메서드와 필드 포함 가능

추상클래스의 사용

  • 유사한 자식 클래스를 묶고자 할 때
  • 불완전한 클래스로서 일부 기능만 제공
  • 자식이 반드시 구현해야 함
  • 자식이 구현하지 않으면 자식도 추상 클래스가 됨
  • 일반 클래스 + 인터페이스의 중간적 성격

예제

abstract class Vehicle {
    abstract void move(); // 추상 메서드
    void stop() { System.out.println("차가 멈췄다."); } // 일반 메서드
}

class Car extends Vehicle {
    void move() { System.out.println("자동차가 달린다!"); } // 구현 필수
}

3. 인터페이스

  • 100% 추상 클래스
  • 모든 메서드는 public abstract (생략 가능)
  • 필드는 public static final만 가능 (상수)
  • 직접 객체 생성 불가
  • 관행적으로 인터페이스명은 형용사 (Runnable, Serializable)

인터페이스 정의

  • interface 키워드 사용
  • 추상 메서드만 선언 (몸체 X)
  • default 또는 static 메서드만 몸체 구현 가능

예제

interface Animal {
    void sound(); // public abstract 자동 적용
}

class Dog implements Animal {
    public void sound() { System.out.println("멍멍"); } 
}

4. 인터페이스의 사용

  • 추상 클래스처럼 자식이 구현
  • 기능적으로 유사한 클래스 묶을 때 사용
  • 인터페이스를 상속받아 새로운 인터페이스 정의 가능
  • 다중 상속 가능 (클래스는 불가능)

인터페이스 상속

  • 자식 인터페이스가 부모 인터페이스를 상속 (extends 사용)
  • 여러 부모 인터페이스를 다중 상속 가능

예제

interface Animal {
    void sound();
}

interface Pet extends Animal {
    void play();
}

class Dog implements Pet {
    public void sound() { System.out.println("멍멍"); }
    public void play() { System.out.println("강아지가 놀고 있음"); }
}

5. 인터페이스의 구현

  • implements 사용
  • 자식 클래스는 인터페이스의 모든 메서드 구현 필수
  • 다중 인터페이스 구현 가능

예제

interface Flyable { void fly(); }
interface Swimable { void swim(); }

class Duck implements Flyable, Swimable {
    public void fly() { System.out.println("오리가 난다!"); }
    public void swim() { System.out.println("오리가 수영한다!"); }
}

6. 디폴트 메소드 (Default Method)

  • 인터페이스에서 몸체를 가진 메소드 선언 가능
  • default 키워드 사용
  • 자식 클래스에서 오버라이딩 가능
  • 기존 인터페이스에 새 메서드 추가 시 기존 코드 수정을 피하기 위해 도입

예제

interface Animal {
    default void sleep() { System.out.println("동물이 잠을 잔다."); }
}

class Dog implements Animal {} // sleep() 오버라이딩 안 해도 사용 가능

7. 추상클래스, 인터페이스, 클래스의 형변환

  • extends와 implements에 따라 상위-하위 자료형 관계 설정
  • 상위 타입 변수 = 하위 객체 참조 가능
  • 동적 바인딩: 실행 시 실제 객체의 메서드 실행

예제

Animal a = new Dog(); // 업캐스팅 (자동)
a.sound(); // "멍멍"

8. 다형성

  • 유사하지만 다양한 기능을 수행
  • 자식 → 부모 형변환 가능
  • 자식의 구현 방식에 따라 동적 바인딩

다형성의 활용 효과

  • 코드 유연성, 재사용성 증가
  • 실제 객체 유형을 명시적으로 다룰 필요 없음

오버라이딩 예제

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

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

Parent p = new Child();
p.show(); // "자식 클래스" (동적 바인딩)

9. 열거형 (Enum)

  • enum 키워드 사용
  • 미리 정의된 값만 가질 수 있음
  • 필드, 생성자, 메소드 포함 가능
  • values() 메서드 제공

예제

enum Color {
    RED, GREEN, BLUE;
}

public class Main {
    public static void main(String[] args) {
        Color c = Color.RED;
        System.out.println(c); // RED
    }
}

10. 익명 클래스 (Anonymous Class)

  • 1회성으로 객체 생성
  • 인터페이스 or 추상 클래스 상속받아 사용
  • 중괄호 {} 내부가 클래스 몸체

예제

abstract class Animal {
    abstract void sound();
}

public class Main {
    public static void main(String[] args) {
        Animal dog = new Animal() { // 익명 클래스
            void sound() { System.out.println("멍멍"); }
        };
        dog.sound(); // "멍멍"
    }
}

11. 중첩 클래스 (Nested Class)

  • 클래스 내부에 또 다른 클래스 정의
  • private, protected 가능
  • 외부 클래스의 멤버와 관련된 작업 처리

1) Non-Static 중첩 클래스 (Inner Class)

  • 외부 클래스 객체가 있어야 사용 가능
  • 외부 클래스의 모든 멤버 접근 가능

예제

class Outer {
    class Inner {
        void show() { System.out.println("내부 클래스!"); }
    }
}

Outer outer = new Outer();
Outer.Inner inner = outer.new Inner(); // 외부 클래스 객체 필요
inner.show(); // "내부 클래스!"

2) Static 중첩 클래스

  • 외부 클래스 객체 없이 사용 가능
  • 정적 멤버만 접근 가능

예제

class Outer {
    static class StaticInner {
        void show() { System.out.println("정적 내부 클래스!"); }
    }
}

Outer.StaticInner inner = new Outer.StaticInner(); // 바로 생성 가능
inner.show(); // "정적 내부 클래스!"

'Java > Java' 카테고리의 다른 글

패키지와 예외처리  (1) 2025.03.18
제네릭과 람다식  (0) 2025.03.18
클래스와 상속  (1) 2025.03.05
Java 기본 문법  (0) 2025.03.05
Java 프로그래밍 개요  (3) 2025.03.05