Programming/Java

[Java9 프로그래밍] 11. 인터페이스

빠모스 2020. 3. 21. 17:02
반응형

인터페이스 선언

 

서비스 공급자(서버)와 사용자(클라이언트) 간의 계약을 표현하는 메커니즘

 

인터페이스 구성

 

필드, member variable

 

인터페이스에서 정의된 모든 필드는 final static이 생략된 상수로 강주된다.

 

메소드

 

  • 추상 메소드 : 반드시 구현 클래스에서 구현 필요
  • 디폴트 메소드 : 구현클래스에서 구현 필요 없음(디폴트로 사용한다는 의미)
  • 정적 메소드 : static 메소드, 객체 없이 바로 호출 가능

=> 원래는 추상메소드만 가능했으나 java8에 와서는 디폴트 메소드와 정적 메소드가 추가되고 java9에 와서 private 메소드까지 추가 가능해짐. 

 

<예시 1>

public interface shoppingService {
	// fields
    double TAX_RATE = 0.005;
    
    // abstract methods
    public List<Product> getAllProducts();
    public List<Product> todayHotDeals();
    public Product getProductDetails(String productId);
    
    // default method
    public default List<Product> sortProducts(List<Product> products {...}
    
    // static method
    public static String versionOf() {...}
}

 

=> abstract methods는 이 인터페이스를 사용하는 클래스는 이 메소드들을 재정의해서 구현하여 사용해야 함

=> 구현된 메소드를 추가하려면 디폴트라는 키워드를 붙여야하고 디폴트 메소드라 부름.

=> 바로 호출할 수 있는 정적 메소드도 추가 가능

 

 

인터페이스 구현

 

  • implements 키워드를 통해 구현
  • 여러 인터페이스를 구현가능 (다중 상속 지원)
public class Sub implements Super1, Super2, Super3 {…}

 

=> 클래스 상속은 하나만 가능하지만 인터페이스는 여러개 상속 가능

 

  • extends 키워드를 통해 확장
  • 인터페이스끼리 상속(확장) 가능
public interface Channel extends Closeable {…}

 

 

디폴트 메소드, Default Methods

 

  • default 제어자를 붙여야 함
  • 자바8에서 새롭게 추가
  • 기존 인터페이스에서 새롭게 메소드 추가를 가능하게 해줌
  • 다중 상속을 지원
  • 추상클래스와의 경계가 모호해짐

<예시 1>

public interface shoppingService {
	// default method
	public default List<Product> sortProducts(List<Product> products) {…}
}

 

=> 기존의 인터페이스들은 추상메소드만 정의 가능했음. 이 인터페이스를 임플리먼트한 메소드들은 이 추상메소드를 오버라이딩해서 재정의해서 구현했다.

여기서 문제점은 기존의 인터페이스의 메소드를 추가하는것이 불가능했다. 

기존에는 이 인터페이스에 새로운 추상메소드를 추가해야 했기 때문에 그 인터페이스 하위의 모든 메소드들이 에러가 났다.

기존의 인터페이스의 메소드들을 쉽게 건드릴 수 없었는데 자바8에서 디폴트 메소드가 생기면서 메소드 추가가 가능해졌다. 왜냐면 디폴트 메소드로 정의를 하고 수정을 하면 하위 클래스나 인터페이스들에는 영향을 안미치기 때문.

 

 

정적 메소드, Static Methods

 

  • static 제어자를 붙여야 함
  • 자바8에서 default method와 더불어 추가됨
  • 정적 메소드만 모아놓은 컴패니언 클래스가 필요 없어짐

예) Collection / Collections, File / Files

팩토리 메소드와 잘 맞음

 

=> 원래는 클래스에만 정적메소드를 사용할 수 있었고, 인터페이스에서는 사용 못했다. 

그래서 Collections, Files와 같은 컴패니언 클래스를 사용했는데 자바8이후에는 인터페이스에도 정적 메소드를 쓸 수 있었기 때문에 필요 없어짐.

 

<예시 1>

public interface shoppingService {
	// static method
	public static String versionOf() {…}	
}

 

ThinkPoint

자바에서 인터페이스란?

인터페이스는 일종의 추상클래스이다. 인터페이스는 추상클래스처럼 추상 메서드를 갖지만 추상클래스보다 추상화 정도가 높아서 추상 클래스와 달리 몸통을 갖춘 일반 메서드 또는 멤버변수를 구성원으로 가질 수 없다.

오직 추상메서드와 상수만을 멤버로 가질 수 있으며, 그 외의 다른 어떠한 요소도 허용하지 않는다. 추상클래스를 부분적으로만 완성된 ‘미완성 설계도’라고 한다면, 인터페이스는 구현된 것은 아무 것도 없고 밑그림만 그려져 있는 ‘기본 설계도’라 할 수 있다.

추상클래스처럼 인터페이스도 완성되지 않은 불완전한 것이기 때문에 그 자체만으로 사용되기보다는 다른 클래스를 작성하는데 도움 줄 목적으로 작성된다.

 

 

실습 코드

지난번 10장 상속 편에서 만들었던 Employee, Manager, RegularEmployee 클래스의 연장선상에서 직원들의 월급과 수당을 주는 인터페이스를 만들어보자.

기존에는 Employee 클래스에서 paySalary가 추상메소드로 들어갔었지만, 이번엔 인터페이스에서 추상메소드로 생성해준다.

인터페이스에서 public abstract는 생략이 가능하다. 만약 수당을 주는 또다른 추상메소드 payAllowance를 만든다면 새로 생긴 메소드이기 때문에 Payable을 임플레멘트한 Employee를 상속받는 두 클래스에서 오버라이딩을 해줘야 한다. 자바8 이전의 자바는 이렇듯 쉽게 인터페이스의 메소드를 바꿀 수 없었다.

 

자바8부터 디폴트 메소드가 나오면서 좀 더 유연하게 바뀌었다. 디폴트 메소드, 정적 메소드, private 메소드를 사용할 수 있게 되었다. 

//// 인터페이스 만들기 ////
package com.acompany.inheritance;

// Payable처럼 추상메소드가 하나인 인터페이스를 FunctionalInterface라고 붙여준다.
@FunctionalInterface //(함수형 인터페이스)
public interface Payable {
    // 월급주는 추상메소드 만들기
    long paySalary(); // public abstract는 생략 가능

    // 수당을 주는 메소드 만들기
    /*long payAllowance();
        //=> 수당은 새로생긴 메소드기때문에 이 Payable을 임플레멘트한 Employee를 상속받은 Manager과 RegularEmployee에서 오버라이딩 하지 않았으므로 문제가 생김.
        // 기존 자바는 이렇게 쉽게 인터페이스의 메소드를 바꿀 수 없었음.
    */

    // 디폴트 메소드 추가
    default long payAllowance() {
        callLocal();
        return 0;
    }
    // => 사용하고싶으면 각 클래스에서 오버라이딩을 하면 되고, 안해도 문제가 없음.

    // Java9 private method 추가
    private void callLocal() {
        // 디폴트 메소드에서 코드가 길어질 때 복잡한 부분을 따로 개별 private 함수로 만든다.
    }
    // 정적 메소드 추가
    static long testStatic() {
        return 1;
    }



}
반응형