공부/Java

[Java-07] 객체지향프로그래밍Ⅱ - 인터페이스, 내부 클래스

줭♪(´▽`) 2021. 3. 3. 22:05

1. 인터페이스(Interface)

1) 인터페이스란?

- 일종의 추상 클래스

- 추상클래스처럼 추상메서드를 갖지만 추상화 정도가 더 높음

- 오직 '추상메서드'와 '상수'만을 멤버로 가짐

 

2) 인터페이스의 작성

 

interface 인터페이스이름 {
    public static final 타입 상수이름 = 값;
    public abstract 메서드이름(매개변수목록);
}

 

- 모든 멤버변수는 public static final이어야 하며, 이를 생략할 수 있음

- 모든 메서드는 public abstract이어야 하며, 이를 생략할 수 있음

(단, static 메서드와 디폴트 메서드는 예외(JDK1.8부터))

interface PlayingCard {
    // 생략 가능하기 때문에 모두 사용 가능
    public static final int SPADE = 4;
    final int DIAMOND = 3;
    static int HEART = 2;
    int CLOVER = 1;
    
    // static메서드와 디폴트 메서드를 제외하고 생략 가능
    public abstract String getCardNumber();
    String getCardKind();
}

 

 

3) 인터페이스의 상속

- 인터페이스는 인터페이스로부터만 상속받을 수 있음

- 클래스와 달리 다중상속 가능

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

interface Attackable {
    void attack(Unit u);
}

interface Fightable extends Movable, Attackable { }

 

 

4) 인터페이스의 구현

- 자신의 정의된 추상메서드의 몸통을 만들어주는 클래스를 작성해야 함

- 추상클래스가 'extends'를 사용하는 반면, 인터페이스는 'implements'를 사용함

- 오버라이딩할 때는 조상의 메서드보다 넓은 범위의 접근 제어자를 지정해야 함

class 클래스이름 implements 인터페이스이름 {
    // 인터페이스에 저장된 추상메서드 구현
}


class Fighter implementes Fightable {
    public void move(int x, int y) { /* 구현 */ }
    public void attack(int x, int y) { /* 구현 */ }
}


// 인터페이스의 메서드 중 일부만 구현한다면 abstract를 붙여 추상클래스로 구현해야 함
abstract class Fighter implementes Fightable {
    public void move(int x, int y) { /* 구현 */ }
}


// 상속과 구현 동시에 가능
class Fighter extends Unit implementes Fightable {
    public void move(int x, int y) { /* 구현 */ }
    public void attack(int x, int y) { /* 구현 */ }
}

 

 

5) 인터페이스를 이용한 다중상속

- 두 개의 클래스로부터 상속받아야 할 경우

① 두 조상클래스 중 비중이 높은 쪽을 선택

② 다른 한쪽은 클래스 내부에 멤버로 포함 or 필요한 부분을 뽑아서 인터페이스로 만든 후 구현

 

6) 인터페이스를 이용한 다형성

- 인터페이스도 클래스와 같이 다형성을 가짐

- 인터페이스 타입의 참조변수로 이를 구현한 클래스의 인스턴스를 참조할 수 있음

- 인터페이스 타입의 형변환 가능

- 메서드의 매개변수 타입으로 인터페이스 사용 가능 (단, 호출 시 인터페이스를 구현한 클래스의 인스턴스를 넘겨줘야 함)

- 리턴타입으로 인터페이스 사용 가능 (메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환함)

interface Fightable { ... }
class Fighter implements Fightable { ... }

class Main {
    ...
    Fightable f = (Fightable)new Fighter();
    또는
    Fightable f = new Fighter();
}

 

 

7) 인터페이스의 장점

① 개발시간 단축

- 인터페이스가 작성되면 이를 사용해서 프로그램을 작성 가능 (선언부만 알면 되기 때문)

 

② 표준화 가능

- 프로젝트에 사용되는 기본 틀을 인터페이스로 작성하여 일관되고 정형화된 개발 가능

 

③ 서로 관계없는 클래스에 관계를 맺어줄 수 있음

- 하나의 인터페이스를 공통적으로 구현하도록 함으로써 관계를 맺어줄 수 있음

 

④ 독립적인 프로그래밍

- 실제 구현에 독립적인 프로그램 작성 가능

- 한 클래스의 변경이 관련된 다른 클래스에 영향을 미치지 않음

 

8) 인터페이스의 이해

- 클래스 사용자(User) / 클래스 제공자(Provider)

- 메서드를 사용(호출)하는 쪽(User)에서는 사용하려는 메서드(Provider)의 선언부만 알면 됨

 

 

9) 디폴트 메서드, static 메서드

- JDK1.8부터 추상 메서드뿐만 아니라 디폴트 메서드와 static 메서드 추가 가능

 

① 디폴트 메서드(default method)

- 추상 메서드의 기본적인 구현을 제공하는 메서드

- 디폴트 메서드가 새로 추가되어도 해당 인터페이스를 구현한 클래스를 변경하지 않아도 됨

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

- 여러 인터페이스의 디폴트 메서드 간의 충돌?

-> 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩해야 함

 

- 디폴트 메서드와 조상 클래스의 메서드 간의 충돌?

-> 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시됨

 

② static 메서드

- 접근 제어자가 항상 public임

- 생략할 수 있음

 

 


 

2. 내부 클래스(inner class)

1) 내부 클래스란?

- 클래스 내에 선언된 클래스

- 두 클래스는 서로 긴밀한 관계에 있음

 

내부 클래스의 장점

- 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있음

- 코드의 복잡성을 줄일 수 있음 (캡슐화)

 

class A {	// 외부 클래스
    ...
    class B {	// 내부 클래스
    	...
    }
}

 

2) 내부 클래스의 종류와 특징 

- 내부 클래스는 선언위치에 따라 4가지로 구분됨 (변수의 선언위치에 따른 종류와 유사)

 

내부 클래스 특  징
인스턴스 클래스
(instance class)
- 외부 클래스의 멤버변수 선언위치에 선언
- 외부 클래스의 인스턴스멤버처럼 다뤄짐
- 주로 외부 클래스의 인스턴스멤버들과 관련된 작업에 사용될 목적
스태틱 클래스
(static class)
- 외부 클래스의 멤버변수 선언위치에 선언
- 외부 클래스의 static멤버처럼 다뤄짐
- 주로 외부 클래스의 static멤버(특히 static메서드)에서 사용될 목적
지역 클래스
(local class)
- 외부 클래스의 메서드나 초기화블럭 안에 선언
- 선언된 영역 내부에서만 사용 가능
익명 클래스
(anonymous class)
- 클래스의 선언과 객체의 생성을 동시에 하는 이름없는 클래스 (일회용)

 

3) 내부 클래스의 선언

- 변수의 선언위치와 동일

- 각 내부 클래스의 선언위치에 따라 같은 선언위치의 변수와 동일한 유효범위(scope)접근성(accessibility)를 가짐

 

4) 내부 클래스의 제어자와 접근성

- 인스턴스 클래스(InstanceInner)와 스태틱 클래스(StaticInner)는 외부 클래스(Outer)의 멤버변수(인스턴스변수, 클래스변수)와 같은 위치에 선언되며 같은 성질을 가짐

- 내부 클래스가 외부 클래스의 멤버와 같이 간주됨

- 즉, 인스턴스멤버와 static멤버 간의 규칙이 내부 클래스에도 적용

- 클래스이므로 제어자(abstract, final 등)접근제어자(private, public 등) 사용 가능

- 컴파일 시 생성되는 파일명은 '외부 클래스명$내부 클래스명. class'

 

5) 익명 클래스(anonymous class)

- 이름이 없는 클래스

- 클래스의 선언과 객체의 생성을 동시에 함

- 단 한번만 사용될 수 있고 오직 하나의 객체만을 생성할 수 있는 일회용 클래스

- 오직 단 하나의 클래스를 상속받거나 단 하나의 인터페이스만 구현할 수 있음

- 이름이 없기 때문에 파일명은 '외부 클래스명$숫자.class'

class Ex {
    Object iv = new Object() { void method() {} };		// 익명 클래스
    static Object cv = new Object() { void method() {} };	// 익명 클래스
    
    void myMethod() {
    	Object lv = new Object() { void method() {} };		// 익명 클래스
    }
}

-> 컴파일하면 4개의 클래스 파일이 생성

Ex.class
Ex$1.class
Ex$2.class
Ex$3.class

 

 

 

 

 

 

참고 - Java의 정석 3rd Edition (저자 : 남궁성, 출판 : 도우출판)