[Lecture/Java] 05강 - 인터페이스와 다형성

김찬미·2025년 5월 28일

5강 - 인터페이스와 다형성

  • 추상 클래스와 인터페이스
  • 다형성
  • 열거 자료형
  • 익명 클래스
  • 중첩 클래스

✅ 추상 클래스와 인터페이스

추상 메소드 abstract

몸체의 구현 없이 형식만 존재하는 메소드

  • 반환형, 메소드 이름과 인자에 대한 선언만 존재
  • 자식 클래스에 상속될 때, 몸체의 구현이 필요함
  • 상반된 의미의 final과는 함께 사용할 수 없음
  • 추상 메소드는 추상 클래스 또는 인터페이스에서 선언되어야 함
abstract class Shape {
	// 모양이 정해지지 않았기 때문에 면적을 계산할 수 없음
    abstract public double getArea();
}

추상 클래스

클래스 정의에 abstract 키워드를 사용

  • 추상 메소드를 포함할 수 있음
  • 데이터 필드, 일반 메소드도 포함 가능
  • 객체 생성을 할 수 없음
    → 구체적이지 못한 불완전한 클래스라는 의미
// Shape이 추상 클래스인 경우
Shape s = new Shape("red"); // 컴파일 오류

🔹추상 클래스의 사용

  • 의미적으로 유사한 자식 클래스를 묶고자 할 때 사용
    → 공통으로 사용할 데이터 필드와 메소드를 추상 클래스에서 정의
  • 추상 클래스는 불완전한 클래스
    → 기능적으로 구현하기 어려운 메소드가 존재
  • 추상 클래스는 자식 클래스로 상속되어 사용됨
    • 자식 클래스에서 추상 메소드를 구현해야 함
    • 이 경우, 자식 클래스는 객체 생성 가능
    • 자식 클래스가 추상 메소드를 구현하지 않음
      → 계속해서 자식 클래스도 추상 클래스이어야 함
  • 추상 클래스는 일반 클래스와 인터페이스의 중간적 성격을 가짐

인터페이스

몸체 없이, 구현되어야 할 메소드의 형식만 정의해 둠
= 100% 추상적 클래스

  • 단, default 인스턴스 메소드와 static 메소드는 몸체를 구현함
    • 모든 메소드의 기본 접근 제어자는 public
  • 데이터 필드는 클래스 상수만 가능(public static final)
  • 참조형이며 직접적 객체 생성은 불가
  • 인터페이스의 이름은 보통 형용사Runnable, Comparable

🔸인터페이스의 정의

  • 메소드의 접근 제어자 → (생략시에도) public abstract
    → 몸체가 없으며, 반환형 이름, 매개변수 목록만 표시
  • 데이터 필드는 항상 (생략 가능) public static final

🔹인터페이스의 사용

  • 의미적으로는 관련이 없으나 기능적으로 유사한 클래스를 묶을 때 인터페이스를 사용할 수 있음
  • 인터페이스를 상속받아 자식 인터페이스를 정의할 수 있음
interface Comparable<T> {
	// 다른 객체와 크기를 비교하는 메소드
	boolean isLargerThan(T o);
}

class Box implements Comparable<Box> {
	private int length, width, height;
    public boolean isLargerThan(Box otherBox) {
		... ...
	}
}

인터페이스의 상속과 구현

1) 자식 인터페이스 - 부모 인터페이스

기존 인터페이스를 상속받아 새로운 인터페이스 정의
키워드 extends 사용

  • 여러 부모 인터페이스를 상속받는 다중 상속도 가능
interface SuperInterface {
	public void func1();
    public void func2();
}

interface SubInterface extends SuperInterface {
	public void func3();
}

2) 자식 클래스 - 부모 인터페이스

자식은 부모가 나열한 기능(추상 메소드)를 구현해야 함
implements 사용

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

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

class Point implements Movable, Scalable {
	... ...
}

디폴트 메소드

인터페이스에서 선언하는 메소드에 기본 구현(몸체)을 넣을 수 있음

  • 자식 클래스에서 상속받을 때, 디폴트 메소드를 그대로 사용할 수 있음

  • 메소드 선언시 default를 사용하고 몸체를 구현해 줌

  • 인터페이스에 새 메소드를 추가할 때, 기존 코드(클래스 정의)의 수정을 피하기 위함

    • 단순히 추상 메소드가 추가된다면, 이전 인터페이스를 구현한 클래스를 수정해야 함
interface DoIt {
	void doSomething();
    int doSomethingElse(String s);
    
    // 아래를 새로 추가한다면?
    default boolean didItWork(int i, String s) {
    	...	...
    }
}

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

  • 인터페이스와 클래스는 모두 사용자 정의형
  • extendsimplements에 따라 상위/하위 자료형 관꼐가 설정됨
  • 상위 유형의 변수는 하위 객체의 참조값을 가질 수 있음
  • 상위 유형의 변수가 가리키는 객체의 실제 유형에 따라 수행되는 메소드가 결정됨(동적 바인딩)

💡 정적 바인딩 VS 동적 바인딩

  • 정적 바인딩: 컴파일 시점에 어떤 메서드가 호출될지 결정
  • 동적 바인딩: 실행 시점에 어떤 메서드가 호출될지 결정
SuperClass sup = new SubClass(); // 자동 형변환
sup.method(); // method()를 SubClass에서 찾음

✅ 다형성

유사하지만 다양한 형상이나 다양한 기능을 가진다는 뜻

  • 한 부모에서 나온 두 자식 객체는 비슷하지만 다름
  • 하나의 클래스에서 오버로딩된 메소드들은 유사하지만 조금씩 다른 기능을 수행함
  • 자식 클래스에서 재정의된 메소드는 부모와 것과 유사하지만 다른 기능을 수행함

형 변환

  • 상속 관계에 있는 클래스 간에는 타입 변환 가능
    → 전혀 다른 두 클래스 간에는 타입 변환 금지
  • 자식(하위) 클래스 ➡️ 부모 클래스: 가능
    • 업캐스팅: 자동으로 형 변환 가능함
    • 참조형 변수는 같은 유형 또는 자식 유형의 객체 참조
    • Aniaml animal = (Animal) new Dog(); // 하위 객체 참조

✅ 열거 자료형

미리 정의된 상수값의 집합을 만들기 위한 자료형

  • enum을 사용하여 정의
  • 열거형으로 선언된 변수에는 미리 지정된 값만 대입 가능
  • 상수값을 배열로 리턴하는 static 메소드인 values()를 제공
enum Day {
	SUNDAY, MONDAY, TUESDAY, 
    WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}

public class Main {
    public static void main(String args[]) {
            Day day = Day.MONDAY;
            for (Day d: Day.values())
                System.out.println(d);
        }
        ......
}

✅ 익명 클래스

  • 일회성으로 1개의 객체를 생성하기 위한 클래스
    → 익명 클래스 정의와 동시에 객체 생성 가능

  • 부모 클래스를 상속받거나 인터페이스를 구현하도록, 익명 클래스 정의

💡 익명 클래스의 정의 방법

  • 아래에서 중괄호가 익명 클래스의 몸체가 됨
  • 부모 클래스를 상속받는 (익명 서브 클래스) 객체를 생성할 때
new 슈퍼클래스() {...}
  • 인터페이스를 구현하는 (익명 구현 클래스) 객체를 생성할 때
new 인터페이스() {...}

✅ 중첩 클래스

외부 클래스 정의 내부에 정의된 또 다른 클래스
→ 내부(inner) 클래스라고도 하며, 외부(outer) 클래스의 멤버가 됨

✔️ 논리적 그룹화를 위한 것

  • 내부 클래스는 보통의 클래스와 다르게 private, protected 클래스가 될 수 있음
  • 일반적으로 내부 클래스는 외부 클래스의 필드와 관련된 작업을 처리

🔹non-static 중첩 클래스

  • 외부 클래스의 객체가 생성된 이후 사용 가능
    → 외부 클래스의 객체와 연관

  • 객체 생성 방법은 외부클래스객체변수.new 내부클래스()

  • 메소드는 this 외에 외부 클래스 객체의 참조(외부클래스.this)를 가지고 있음
  • 외부 클래스의 모든 멤버에 접근할 수 있음

🔹static 중첩 클래스

  • 외부 클래스 객체 생성과 무관하게 사용 가능
  • 외부 클래스의 정적 멤버에 접근할 수 있음

profile
백엔드 지망 학부생

0개의 댓글