기본 콘텐츠로 건너뛰기

방송대 방통대 Java프로그래밍 5강 - 인터페이스와 다형성 - 요약 노트 시험족보 예상문제 - 올에이클래스

Java프로그래밍 5강 - 인터페이스와 다형성

Java프로그래밍 5강 - 인터페이스와 다형성

추상 클래스와 인터페이스를 이용해 공통 규약을 설계하고, 상속·형변환·오버라이딩으로 다형성을 구현하는 방법을 학습한다. 이어서 미리 정한 상수 집합을 표현하는 열거형과 일회성 구현을 위한 익명 클래스, 클래스 내부의 중첩 클래스까지 살펴본다.

제1장 추상 메서드와 추상 클래스

1. 추상 메서드

추상 메서드는 메서드 정의에 abstract 키워드를 사용하고 몸체 없이 형식만 선언하는 메서드이다. 반환형, 메서드 이름, 매개변수 목록만 존재하며 실제 동작은 이를 상속한 자식 클래스가 구현한다. 예를 들어 모양이 정해지지 않은 일반적인 도형은 면적 계산식을 하나로 정할 수 없으므로 getArea()의 규약만 선언할 수 있다.

abstract class Shape {
    abstract public double getArea();
}

추상 메서드는 자식 클래스에서 구현되어야 하므로 상반된 의미의 final과 함께 사용할 수 없다. 또한 추상 메서드는 추상 클래스 또는 인터페이스 안에서 선언되어야 한다.

2. 추상 클래스의 특징

추상 클래스는 클래스 선언에 abstract를 붙인 불완전한 클래스이다. 추상 메서드를 포함할 수 있으며, 데이터 필드와 몸체가 있는 일반 메서드도 함께 가질 수 있다. 중요한 제한은 추상 클래스 자체의 객체를 직접 만들 수 없다는 점이다. new Shape()처럼 인스턴스를 생성하면 컴파일 오류가 발생한다.

추상 클래스는 의미적으로 비슷한 자식 클래스들의 공통 필드와 메서드를 한곳에 정의할 때 사용한다. 자식 클래스는 추상 클래스를 extends로 상속한 뒤 모든 추상 메서드를 구현해야 객체를 만들 수 있다. 구현하지 않은 추상 메서드가 하나라도 남아 있다면 그 자식 클래스 역시 추상 클래스로 선언해야 한다.

시험 핵심: 추상 클래스는 객체를 직접 생성할 수 없지만 필드, 생성자, 일반 메서드와 추상 메서드를 함께 가질 수 있다. 완전한 구현을 제공한 구체적 자식 클래스에서 객체를 생성한다.

3. 추상 클래스의 역할

추상 클래스는 완전한 일반 클래스와 순수한 규약 중심의 인터페이스 사이에 있는 성격을 가진다. 여러 자식 클래스가 공유하는 상태와 구현은 일반 필드와 메서드로 제공하고, 자식마다 달라야 하는 기능은 추상 메서드로 남겨 둔다. 이 구조는 공통 코드를 재사용하면서도 자식 클래스에 특정 동작의 구현을 강제한다.

제2장 인터페이스의 정의와 사용

1. 인터페이스의 개념

인터페이스는 구현해야 할 동작의 형식을 정의하는 100% 추상적 규약으로 설명할 수 있다. 전통적인 추상 메서드는 몸체가 없고 기본 접근 제어자가 public abstract이다. 인터페이스의 데이터 필드는 클래스 상수만 가능하며 기본적으로 public static final이다. 인터페이스는 참조형이지만 그 자체의 객체를 직접 만들 수 없다.

인터페이스 이름은 일반적으로 형용사 형태를 사용한다. 표준 라이브러리의 Runnable, Serializable, Comparable이 대표적이다. 클래스가 무엇인지를 표현하는 상속과 달리, 인터페이스는 객체가 어떤 능력이나 규약을 제공하는지 표현하는 데 효과적이다.

2. 인터페이스 선언

클래스 선언의 class 대신 interface 키워드를 사용한다. 추상 메서드의 public abstract는 생략하는 것이 일반적이며, 메서드 몸체 없이 반환형·이름·매개변수만 작성한다. 필드의 public static final도 생략할 수 있지만 그 성격은 변하지 않는다.

interface ComparableBox<T> {
    boolean isLargerThan(T other);
}

현대 Java 인터페이스는 몸체가 있는 default 인스턴스 메서드와 static 메서드도 가질 수 있다. 이 경우에는 반드시 메서드 몸체를 작성한다. 인터페이스는 클래스 상수도 가질 수 있으나 인스턴스 상태를 저장하는 일반 필드는 가질 수 없다.

3. 인터페이스 구현

클래스는 implements를 사용해 인터페이스를 구현한다. 인터페이스의 추상 메서드는 암묵적으로 public이므로 구현 메서드도 public이어야 한다. 구현하지 않은 메서드가 남아 있다면 해당 클래스는 추상 클래스로 선언해야 한다.

interface Figure {
    double getArea();
}

class Triangle implements Figure {
    private double height, width;

    public Triangle(double h, double w) {
        height = h;
        width = w;
    }

    public double getArea() {
        return height * width * 0.5;
    }
}
추상 클래스나 인터페이스를 참조 변수의 자료형으로 사용할 수 있다. 이 참조 변수에는 해당 추상 클래스를 상속하거나 인터페이스를 구현한 자식 객체의 참조값을 대입할 수 있다.

제3장 인터페이스 상속과 다중 구현

1. 인터페이스 사이의 상속

인터페이스가 다른 인터페이스를 상속할 때는 extends를 사용한다. 자식 인터페이스는 부모 인터페이스의 추상 메서드를 물려받고 새 메서드를 추가할 수 있다. 클래스 상속과 달리 인터페이스는 여러 인터페이스를 동시에 상속하는 다중 상속이 가능하다.

interface SuperInterface {
    void func1();
    void func2();
}

interface SubInterface extends SuperInterface {
    void func3();
}

2. 클래스의 다중 인터페이스 구현

Java 클래스는 하나의 클래스만 직접 상속할 수 있지만 여러 인터페이스를 동시에 구현할 수 있다. 구현할 인터페이스 이름을 쉼표로 나열하며, 구체 클래스는 각 인터페이스가 요구하는 모든 추상 메서드를 구현해야 한다.

interface Movable {
    void add(double dx, double dy);
    void sub(double dx, double dy);
}

interface Scalable {
    void mul(double scale);
    void div(double scale);
}

class Point implements Movable, Scalable {
    // 네 메서드를 모두 구현
}
관계키워드특징
클래스가 클래스 상속extends직접 상속은 하나의 부모 클래스
인터페이스가 인터페이스 상속extends여러 부모 인터페이스 상속 가능
클래스가 인터페이스 구현implements여러 인터페이스 구현 가능

제4장 디폴트 메서드와 형변환

1. 디폴트 메서드

디폴트 메서드는 인터페이스에서 default 키워드와 몸체를 함께 작성한 인스턴스 메서드이다. 이를 상속한 클래스는 기본 구현을 그대로 사용할 수 있고 필요하면 오버라이딩할 수 있다.

디폴트 메서드의 중요한 목적은 인터페이스의 진화이다. 기존 인터페이스에 추상 메서드를 새로 추가하면 그 인터페이스를 구현한 모든 클래스를 즉시 수정해야 한다. 새 기능을 디폴트 메서드로 제공하면 기존 구현 클래스의 소스 수정 없이 기본 동작을 공급할 수 있다.

interface DoIt {
    void doSomething();

    default boolean didItWork(int i, String s) {
        return i > 0 && s != null;
    }
}

2. 상위 자료형과 하위 객체

클래스와 인터페이스는 모두 사용자 정의 자료형이다. extendsimplements 관계가 만들어지면 상위 자료형의 변수에 하위 객체의 참조값을 대입할 수 있다. 예를 들어 SuperClass sup = new SubClass();는 자동 형변환인 업캐스팅이다.

컴파일러는 호출하려는 메서드가 참조 변수의 선언 자료형에 존재하는지 확인한다. 실행할 때는 참조된 객체의 실제 유형을 기준으로 오버라이딩된 메서드를 선택한다. 이를 동적 바인딩이라 한다.

구분: 호출 가능 여부는 참조 변수의 선언 자료형을 기준으로 검사하지만, 오버라이딩된 메서드의 실제 실행은 객체의 실제 자료형이 결정한다.

제5장 다형성과 오버라이딩

1. 다형성의 의미

다형성은 서로 유사한 객체가 다양한 형상이나 기능을 나타내는 성질이다. 한 부모에서 나온 자식 객체들은 공통적인 특징을 가지면서 서로 다른 동작을 수행할 수 있다. 하나의 클래스 안에서 같은 이름을 다른 매개변수로 정의하는 오버로딩과, 상속 관계에서 같은 시그니처의 메서드 구현을 바꾸는 오버라이딩이 이러한 다양성을 보여 준다.

2. 상속 관계의 형변환

타입 변환은 상속 관계에 있는 클래스 사이에서만 가능하며 전혀 관계없는 클래스끼리의 형변환은 금지된다. 자식 클래스에서 부모 클래스 방향의 업캐스팅은 참조 손실 없이 자동으로 이루어진다. 부모 자료형의 참조 변수는 같은 부모 유형 또는 그 자식 유형의 객체를 참조할 수 있다.

상위 자료형 변수를 다시 하위 자료형으로 바꾸는 다운캐스팅은 객체의 실제 유형이 맞는지 확인해야 한다. 선언 자료형만 바꾼다고 객체 자체의 실제 유형이 달라지는 것은 아니다. 다형성을 이용하면 객체의 구체적인 자식 유형을 매번 명시하지 않고도 공통 상위 자료형으로 여러 객체를 처리할 수 있어 코드의 유연성과 재사용성이 높아진다.

3. 오버라이딩과 동적 바인딩

부모 클래스에서 상속받은 메서드를 자식 클래스가 같은 이름, 매개변수, 반환형으로 다시 구현하면 오버라이딩이 된다. 같은 상위 타입의 변수로 호출하더라도 실제로 연결된 객체가 B이면 B의 메서드, C이면 C의 메서드가 실행된다.

class A {
    public void func() { System.out.println("A"); }
}
class B extends A {
    public void func() { System.out.println("B"); }
}
class C extends B {
    public void func() { System.out.println("C"); }
}

A value = new B();
value.func();          // B
value = new C();
value.func();          // C

인터페이스에서도 같은 원리가 적용된다. 서로 다른 구현 클래스가 같은 인터페이스 메서드를 각자 다르게 구현하면 인터페이스 자료형 하나로 다양한 동작을 호출할 수 있다.

제6장 추상 클래스와 인터페이스 비교

구분추상 클래스인터페이스
선언abstract classinterface
관계 설정클래스가 extends클래스가 implements
인스턴스 필드가질 수 있음가질 수 없고 상수만 가능
메서드추상 메서드와 일반 메서드추상 메서드, default·static 메서드
직접 객체 생성불가능불가능
다중 관계클래스 직접 상속은 하나여러 인터페이스 구현 가능
주요 목적공통 상태와 구현을 공유하는 계층서로 다른 클래스에 공통 능력과 규약 부여

공통 필드와 구현을 자식에게 물려줄 필요가 크다면 추상 클래스가 적합하다. 상속 계층과 무관한 여러 클래스에 같은 기능 규약을 적용하거나 다중 역할을 부여하려면 인터페이스가 유리하다. 둘은 경쟁 관계가 아니라 설계 목적에 따라 함께 사용할 수 있는 도구이다.

제7장 열거 자료형

1. 미리 정의된 상수의 집합

열거형은 미리 정의된 상수값의 집합을 만들기 위한 자료형이며 enum으로 선언한다. 열거형 변수에는 선언된 상수만 대입할 수 있으므로 임의의 값이 들어오는 것을 막을 수 있다. 모든 상수를 배열로 반환하는 정적 메서드 values()가 자동으로 제공되어 향상된 for문으로 순회할 수 있다.

enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY
}

Day day = Day.MONDAY;
for (Day value : Day.values()) {
    System.out.println(value);
}

2. 필드, 메서드와 생성자

열거형은 단순한 정수 상수 목록이 아니라 필드와 메서드를 포함할 수 있는 자료형이다. 상수 선언은 필드나 메서드보다 먼저 오며, 다른 멤버가 이어지면 상수 목록 끝을 세미콜론으로 마쳐야 한다. 각각의 열거 상수는 열거형의 인스턴스이며 열거형이름.상수값으로 접근한다.

열거형 생성자는 열거 상수 객체의 필드를 초기화하며 열거형과 같은 이름을 가진다. 접근 제어자는 생략하거나 private이어야 한다. 생성자는 각 상수가 만들어질 때 한 번씩 자동 호출되며 외부에서 임의로 열거형 객체를 생성하는 용도로 사용할 수 없다.

enum BaseballTeam {
    LG(40, 30), SS(30, 40), KT(20, 50);

    private final int win;
    private final int lose;

    private BaseballTeam(int win, int lose) {
        this.win = win;
        this.lose = lose;
    }

    public double winsRate() {
        return win * 100.0 / (win + lose);
    }
}

제8장 익명 클래스

1. 이름 없는 일회성 클래스

익명 클래스는 일회성으로 하나의 객체를 만들기 위한 이름 없는 클래스이다. 클래스 정의와 객체 생성을 동시에 수행한다. 부모 클래스를 상속한 익명 서브 클래스 또는 인터페이스를 구현한 익명 구현 클래스를 만들 수 있다.

MyInterface value = new MyInterface() {
    public void method() {
        System.out.println("익명 구현 클래스");
    }
};

부모 클래스의 익명 서브 클래스는 new 부모클래스() { ... }, 인터페이스의 익명 구현 클래스는 new 인터페이스() { ... } 형태로 작성한다. 별도 클래스 이름이 필요하지 않은 짧은 구현을 한 번만 사용할 때 유용하다.

2. 참조 자료형에 따른 접근 범위

익명 클래스 객체를 부모 자료형 변수에 저장하면 컴파일러는 그 부모 자료형에 선언된 멤버만 접근할 수 있는지 검사한다. 익명 클래스가 새 필드나 새 메서드를 추가했더라도 부모 자료형에 선언되지 않았다면 그 참조 변수로 직접 호출할 수 없다. 반면 부모 메서드를 오버라이딩했다면 동적 바인딩으로 익명 클래스의 구현이 실행된다.

제9장 중첩 클래스

1. 중첩 클래스의 개념

중첩 클래스는 외부 클래스 정의 내부에 선언된 또 다른 클래스이며 내부 클래스라고도 한다. 외부 클래스의 멤버가 되어 관련된 작업을 논리적으로 묶는 데 사용한다. 중첩 클래스는 일반적인 최상위 클래스와 달리 private 또는 protected로 선언할 수도 있다.

2. non-static 중첩 클래스

non-static 중첩 클래스의 객체는 외부 클래스 객체가 만들어진 뒤에 생성할 수 있으며 외부 객체와 연결된다. 생성 형식은 외부클래스객체.new 내부클래스()이다. 내부 클래스의 메서드는 this 외에도 외부클래스.this를 사용해 연결된 외부 객체를 참조하며 외부 클래스의 모든 멤버에 접근할 수 있다.

OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();

매개변수, 내부 클래스 필드, 외부 클래스 필드의 이름이 모두 x라면 x는 매개변수, this.x는 내부 객체의 필드, OuterClass.this.x는 외부 객체의 필드를 가리킨다.

3. static 중첩 클래스

static 중첩 클래스는 외부 클래스 객체의 생성 여부와 무관하게 사용할 수 있다. 외부 객체와 연결되지 않으므로 외부 클래스의 정적 멤버에 직접 접근할 수 있다. non-static 내부 클래스가 외부 객체의 인스턴스 상태를 다루는 데 적합하다면, static 중첩 클래스는 외부 클래스의 이름 공간 안에 관련 자료형을 묶되 개별 외부 객체와 연결할 필요가 없을 때 적합하다.

4. 내부 클래스 활용

내부 클래스는 외부 클래스의 구현 세부 사항을 감추면서 외부 필드와 긴밀히 협력하는 도우미 객체를 만들 때 유용하다. 강의의 반복자 예에서는 Iterator<Integer>를 구현하는 private 내부 클래스가 외부 배열에 접근하여 짝수 인덱스의 값만 차례로 반환한다. 반복 로직을 외부에 노출하지 않고 관련 클래스 내부에 캡슐화한 예이다.

핵심 개념 정리

  • 추상 메서드는 몸체가 없으며 구체적 자식 클래스가 구현해야 한다.
  • 추상 클래스는 직접 객체를 만들 수 없지만 필드, 일반 메서드와 추상 메서드를 함께 가질 수 있다.
  • 인터페이스의 추상 메서드는 기본적으로 public abstract, 필드는 public static final이다.
  • 인터페이스끼리는 extends, 클래스가 인터페이스를 구현할 때는 implements를 사용한다.
  • 클래스는 여러 인터페이스를 구현할 수 있고, 디폴트 메서드는 기존 구현을 깨뜨리지 않고 기본 기능을 추가한다.
  • 상위 자료형 변수는 하위 객체를 참조할 수 있으며 오버라이딩된 메서드는 실제 객체 유형에 따라 동적으로 선택된다.
  • 열거형은 미리 정의한 상수 집합이며 필드, 메서드, private 생성자를 포함할 수 있다.
  • 익명 클래스는 이름 없이 한 번 사용할 서브 클래스나 인터페이스 구현 객체를 동시에 정의·생성한다.
  • non-static 내부 클래스는 외부 객체와 연결되고, static 중첩 클래스는 외부 객체 없이 사용할 수 있다.

이번 강의의 중심은 상위 자료형으로 공통 규약을 표현하고 실제 객체가 각자의 동작을 수행하게 만드는 것이다. 추상 클래스는 공통 상태와 구현을, 인터페이스는 공통 능력과 규약을 표현한다. 여기에 형변환과 오버라이딩에 따른 동적 바인딩이 결합되면 구체 클래스에 덜 의존하면서 확장 가능한 다형적 프로그램을 작성할 수 있다.

예상문제 20선

1. 추상 메서드에 대한 설명으로 옳은 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
추상 메서드는 구현 몸체가 없는 규약이며 추상 클래스나 인터페이스에서 선언한다.

2. 추상 클래스에 대한 설명으로 옳지 않은 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
추상 클래스는 불완전한 클래스이므로 직접 인스턴스를 만들 수 없고 구체적 자식 클래스의 객체를 생성한다.

3. 추상 클래스를 상속한 자식 클래스가 모든 추상 메서드를 구현하지 않은 경우에는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
구현되지 않은 추상 메서드가 남으면 그 클래스 역시 불완전하므로 추상 클래스로 선언해야 한다.

4. 인터페이스의 일반적인 필드가 갖는 성격은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
인터페이스의 필드는 생략해 적더라도 public static final인 클래스 상수이다.

5. 클래스가 인터페이스를 구현할 때 사용하는 키워드는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
클래스는 implements 인터페이스명으로 규약을 구현한다. 인터페이스 사이의 상속은 extends이다.

6. 인터페이스를 구현한 구체 클래스의 메서드 접근 제어자로 알맞은 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
인터페이스의 추상 메서드는 public이므로 구현 메서드의 접근 범위를 더 좁힐 수 없다.

7. Java에서 가능한 선언은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
클래스의 직접 상속은 하나지만 여러 인터페이스의 규약을 동시에 구현할 수 있다.

8. 인터페이스의 디폴트 메서드를 사용하는 주된 이유는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
디폴트 메서드는 몸체가 있는 기본 구현을 제공하여 인터페이스를 확장할 때 기존 구현 코드의 수정을 줄인다.

9. A value = new B();에서 B가 A를 상속할 때 이 대입은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
자식 객체의 참조를 상위 자료형 변수에 넣는 변환은 자동으로 허용되는 업캐스팅이다.

10. 상위 자료형 변수가 자식 객체를 참조하고 오버라이딩 메서드를 호출할 때 실제 실행 메서드를 정하는 기준은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
동적 바인딩에 의해 실행 시 객체의 실제 자료형에 있는 오버라이딩 구현이 선택된다.

11. 다형성의 활용 효과로 가장 적절한 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
다형성은 구체적인 자식 타입에 대한 의존을 줄이고 상위 규약을 통해 여러 구현을 같은 방식으로 다루게 한다.

12. 열거형의 모든 상수를 배열로 반환하는 메서드는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
모든 열거형에는 선언된 상수들을 배열로 돌려주는 정적 메서드 values()가 제공된다.

13. 필드나 메서드가 있는 열거형에서 상수 목록 뒤에 필요한 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
열거 상수 선언 뒤에 필드, 생성자나 메서드가 이어지면 상수 목록을 세미콜론으로 마쳐야 한다.

14. 열거형 생성자에 대한 설명으로 옳은 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
열거형 생성자는 각 상수 객체의 필드를 초기화하며 외부의 임의 객체 생성을 허용하지 않는다.

15. 익명 클래스에 대한 설명으로 옳은 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
익명 클래스는 별도 이름 없이 부모를 상속하거나 인터페이스를 구현한 객체를 그 자리에서 만든다.

16. 부모 자료형 변수에 저장된 익명 서브 클래스 객체에 대한 설명은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
컴파일러는 참조 변수의 선언 자료형에 해당 멤버가 있는지 확인한다. 오버라이딩된 메서드는 실제 객체 구현이 실행된다.

17. non-static 내부 클래스 객체를 만드는 올바른 순서는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
non-static 내부 클래스는 특정 외부 객체와 연결되므로 외부 인스턴스가 먼저 필요하다.

18. 내부 클래스에서 외부 클래스 객체의 같은 이름 필드 x를 명시하는 표현은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
this.x는 내부 객체의 필드이고 OuterClass.this.x는 연결된 외부 객체의 필드이다.

19. static 중첩 클래스의 특징은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
static 중첩 클래스는 개별 외부 객체와 연결되지 않으며 외부 클래스의 정적 멤버에 직접 접근할 수 있다.

20. 추상 클래스와 인터페이스의 선택 기준으로 적절한 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
두 도구는 목적이 다르며 공통 구현과 상태 공유 여부, 다중 역할 규약의 필요성을 기준으로 선택한다.

댓글