[스터디]Java의 정석 13일차

Kristopher·2022년 1월 8일
0

Java 스터디

목록 보기
13/31

(Ch7) 6. 추상클래스 ~ 7.9 디폴트 메소드와 static 메소드

추상클래스란 무엇인가?

추상 클래스란 미완성 메소드를 포함하고 있는 클래스를 의미한다. 메소드의 선언부만 정의하고 구현부가 없는 상태이기 때문에 무의미하다고 생각할 수 있지만 클래스 작성의 틀을 제공하는 역할을 수행한다. 공통부분을 추상 클래스로 적어놓고 각자의 기능에 맞추어 구현하는 것이 훨씬 효율적이기 때문이다.

// 추상 클래스는 abstract를 붙인다.
abstract class class_name{
    //추상 메소드는 abstract를 붙이고 구현부가 없으므로 {} 대신 ;를 사용
    abstract void method_name ();
}

그렇다면 추상클래스를 작성해야한다면 어떤 과정을 거쳐야 할까? 추상클래스는 틀을 제공하는 역할을 하므로 기존 클래스의 공통적인 부분을 뽑아 조상 클래스를 만드는 과정을 거치면 된다. 이후 구체화를 통해 클래스를 구현, 확장해나갈 수 있다.

추상화 : 클래스 간의 공통부분을 찾아내서 조상클래스를 만드는 과정
구체화 : 조상클래스를 상속받아 클래스를 구현, 확장하는 과정

abstract class Unit {
    int x,y;
    abstract void move(int x, int y);
    void stop() {/* 생략 */}
}

class Marine extends Unit {
    void move(int x, int y) {/* 생략 */}
    void stimPack() {/* 생략 */}
}

class Tank extends Unit {
    void move(int x, int y) {/* 생략 */}
    void changeMode() {/* 생략 */}
}

class Dropship extends Unit {
    void move(int x, int y) {/* 생략 */}
    void load() {/* 생략 */}
    void unload() {/* 생략 */}
}

위의 코드에서 각 유닛들이 가지는 공통적인 성질을 Unit이라는 조상 클래스로 추상화하고, 각 유닛에서 상속을 받아 구체화 시키고 추가적인 특징에 대해 구현하는 코드를 작성하였다.

인터페이스란 무엇인가?

인터페이스는 추상클래스보다 추상화정도가 높다고 이해할 수 있다. 추상화 정도가 높기 때문에 일반 메소드 또는 멤버변수를 가질 수 없고 추상메소드와 상수만을 멤버로 가질 수 있다. 추상 클래스가 미완성 설계도라면 인터페이스는 기본 설계도의 느낌이다.

인터페이스를 작성할 때는 class 대신 interface를 사용하고, 일반적인 클래스와 달리 멤버들에 대한 제약도 존재한다.

모든 멤버변수는 public static final 이어야 한다.(생략 가능)
모든 메소드는 public abstract이어야 한다.(생략 가능)

위의 두가지 제약은 예외없이 적용되어야 하므로 멤버변수와 메소드 제약 모두 생략이 가능하다.

인터페이스의 상속과 구현

인터페이스는 인터페이스로부터만 상속받을 수 있으며, 단일 상속만 가능한 클래스와 달리 인터페이스는 다중상속이 가능하다. 인터페이스도 그 자체로는 인스턴스를 생성할 수 없기 때문에 구현을 통해 자신에게 정의된 추상 메소드의 몸통을 만들어주어야 한다.

class class_name implements interface_name{
    // 인터페이스에 정의된 추상 메소드 구현
}

만일 인터페이스의 모든 메소드를 구현하는 것이 아니라 일부만 구현한다면 클래스에 abstract를 붙여 추상클래스로 선언해야 한다. 오버라이딩시 주의할 점은 조상의 메소드보다 접근 제어자를 넓게 지정해야 하는데 인터페이스에 있는 모든 메소드는 public이므로 구현하는 클래스 메소드의 접근제어자도 public이어야 한다.

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

인터페이스도 클래스를 통해 구현이 이루어지므로 클래스의 조상이라고 생각할 수 있다. 그렇기에 인터페이스 타입의 참조변수로 구현한 클래스의 인스턴스를 참조할 수 있으며 형변환도 가능하다. 매개변수로 인터페이스 타입을 갖는다는 의미는 메소드 호출시에 해당 인터페이스를 구현한 클래스의 인스턴스를 매개변수로 제공해야한다는 것이다. 인터페이스 자체로는 인스턴스를 생성할 수 없으니 구현된 클래스의 인스턴스를 넘겨주는 것이다.

리턴타입 또한 매개변수와 유사한데, 리턴타입이 인터페이스인 경우 리턴값으로 해당 인터페이스를 구현한 클래스의 인스턴스를 반환해야 한다.

인터페이스의 장점

추상 클래스만으로도 충분할거 같다는 생각이 드는데 인터페이스를 사용하였을 때 장점은 무엇일까? 정리해보면 다음과 같다.

  • 메소드 호출부분을 다루는 것과 구현부분을 다루는 것을 불리하여 개발시간을 단축시킬 수 있다.
  • 인터페이스로 공통된 틀을 제공하기 때문에 표준화가 가능하다.
  • 서로 관계 없는 클래스들에게 인터페이스를 구현하게 함으로써 관계를 맺어줄 수 있다.
  • 클래스들 사이에 인터페이스를 넣어 독립적으로 만들면 독립적인 프로그래밍이 가능하다.

default 메소드와 static 메소드

인터페이스의 규칙 중에서 추상 메소드만을 선언할 수 있다는 것을 보았다. 하지만 JDK1.8부터 default 메소드와 static 메소드를 추가할 수 있게 되었다. static 메소드의 경우 인스턴스 생성과 관련이 없기 때문에 인터페이스에 추가하는 것이 문제가 되지 않는다.

default 메소드는 새로운 메소드를 인터페이스 추가하는 이슈에서 출발한다. 인터페이스에 새로운 메소드를 추가하면 해당 메소드를 구현하고 있는 모든 클래스에서 추가된 메소드를 구현해야 한다. 이러한 이슈를 막기 위해 인터페이스에서 default 메소드를 추가할 수 있도록 하여 해당 인터페이스를 구현한 클래스에 변경이 이루어지지 않아도 된다. 조상 클래스에 새로운 메소드를 추가한 것과 동일한 효과가 발생한 것이다.

주의해야할 점은 새로 추가된 default 메소드가 기존 메소드와 이름이 중복되는 경우이다. 이같은 문제가 발생하면 다음 두가지 규칙을 적용하여 해결한다.

  1. 여러 인터페이스의 dafault 메소드끼리 충동하는 경우
  • 인터페이스를 구현한 클래스에서 메소드를 default 메소드를 오버라이딩 한다.
  1. default 메소드와 조상 클래스의 메소드끼리 충돌하는 경우
  • 조상 클래스의 메소드가 상속되고 default 메소드는 무시된다.

규칙이 떠오르지 않는 경우에는 필요한 쪽의 메소드를 오버라이딩하여 사용하면 된다.

Reference

Java의 정석
남궁성의 정석코딩

profile
개발자 지망생입니다.

0개의 댓글