자바 스터디 8주차 : 인터페이스

hwanse·2021년 2월 16일
0

Java

목록 보기
9/14

이 글은 백기선님의 라이브 스터디 참여 및 학습 내용에 관한 정리한 글입니다.





학습 목표

  1. 인터페이스 정의하는 방법
  2. 인터페이스 구현하는 방법
  3. 인터페이스 레퍼런스를 통해 구현체를 사용하는 방법
  4. 인터페이스 상속
  5. 인터페이스의 기본 메소드 (Default Method), 자바 8
  6. 인터페이스의 static 메소드, 자바 8
  7. 인터페이스의 private 메소드, 자바 9



인터페이스 정의 방법

인터페이스(interface)란 다른 클래스를 작성할 때 기본이 되는 틀을 제공하며, 다른 클래스 사이의 중간 매개 역할까지 담당하는 일종의 추상 클래스를 의미한다고 한다.


선언 방법
1. 인터페이스 선언시 interface키워드를 사용한다.
2. 인터페이스의 모든 메소드는 public abstract 모든 필드는 public static final 이어야 한다. (단, 자바8 이후에는 static 메소드, default 메소드는 예외)
3. 위 키워드들은 개발자가 생략을 해도 되며, 컴파일러가 자동으로 해당 키워드를 추가해준다.

선언 예시

interface InterfaceTest {  // 'interface' 키워드를 통해 선언
  public static fianl NUMBER = 1;
  public abstract testRun();  // 구현부가 없는 추상 메소드
}

인터페이스 사용시 장점

  • 프로젝트 개발 시 일관되고 정형화된 개발을 위한 표준화가 가능
  • 클래스 작성과 인터페이스의 구현을 동시에 진행할 수 있으므로, 개발 시간의 단축이 가능
  • 클래스와 클래스 간의 관계를 인터페이스로 연결하게 되면, 클래스마다 독립적인 프로그래밍이 가능


인터페이스 구현 방법

인터페이스 또한 추상클래스와 마찬가지고 자신이 직접 인스턴스를 생성할 수 없다. 인터페이스가 포함하고 있는 추상 메소드를 구현화할 클래스가 필요한 것이다. 자바에서 클래스가 인터페이스를 구현화할 때에는 implements 키워드를 사용하면 된다. 클래스 상속에서 사용하던 extends 키워드와는 다르며, 인터페이스 구현화는 복수로 구현화가 가능하다.

class Test implements InterfaceName {
}


그런데 인터페이스 정의에서 의문점이 한가지 있는데 바로 추상 클래스라는 용어다. 자바에서는 추상 클래스가 있는데 인터페이스도 추상 클래스와 비슷하다고 하니 이해가 가질않는다.

추상 클래스, 인터페이스 차이점

자바에서 추상 클래스는 추상 메소드, 필드, 생성자, 일반 메소드를 포함하는 것이 가능하다. 그러나 인터페이스는 오직 추상 메소드, 상수만을 가질 수 있다. (여기서 자바8 이후 부터는 default 메소드와 static 메소드가 추가됨)

여기서 위와 같은 선언 방식에 대한 차이가 있는 것은 알겠으나 개발자가 이 비슷한 두 가지를 어떤 상황에 활용하는 것이 좋을지에 대한 의미 구분이 모호한 것 같다. 그러던 중 인터페이스와 추상 클래스의 역할의 차이를 구분에 대한 내용을 찾아보면서 다른 블로그의 내용이 좋아 참고했습니다.
- 참고 블로그 : https://myjamong.tistory.com/150


  • 추상클래스는 is a (~ 이다)
  • 인터페이스는 has a (~ 을 할 수 있는)

추상 클래스는 특정 공통의 객체를 추상화할 때 사용하는 것이 좋고 인터페이스는 해당 객체의 행위에 대해서 추상화할 때 사용하는 것이 좋다.

예시) 다음은 아래 텍스트를 코드로 구현화 해본 것 입니다.
개발자는 사람(공통 객체)이다.
개발자는 코딩(행위)을 할 수 있다.

class Person {
  String name;
  int age;
}

interface Development {
  public abstact void coding();
}

public class Developer extends Person implements Development {
  
  String language;
  
  public Developer(String name, int age, String language) {
    super(name, age);
    this.language = language;
  }
  
  @Override
  public void coding() {
    System.out.println(language + " 개발자는 " + language + "를 코딩중이다."); 
  }
  
}


인터페이스 레퍼런스를 통해 구현체를 사용하는 방법

자바는 인터페이스를 통해 다형성을 이용할 수 있다. A라는 클래스에서 B라는 인터페이스를 구현화한 객체라면 B 타입의 참조변수에 A 클래스의 객체를 참조할 수 있다.

interface B {
  void run();
}

class A implements B {

  @Override
  public void run() {
    System.out.println("running..");
  }
  
}

class Main {
  public static void main(String[] args) {
    B parent = new A();  // B 라는 인터페이스 타입에 A 객체를 주입
    parent.run();    
  }
}


인터페이스 상속

인터페이스 상속에서는 클래스와 다르게 다중 상속이 가능하다. 클래스에서는 부모 클래스의 메소드가 자손에서 충돌나는 문제를 방지하기 위해서인데, 인터페이스에서는 존재하는 추상 메소드는 선언부만 존재하기 때문에 충돌날 가능성이 없기 때문에 다중 상속을 할 수 있다.
그러나, 다중 상속할 시 상위 인터페이스에 있는 메소들 중에서 메소드명, 매개변수 형식이 같으나 리턴타입은 서로 다른 메소드가 있다면 이 경우에는 다중 상속이 불가하여 컴파일 에러를 발생시킨다.

위와 같이 C라는 인터페이스가 A와 B 인터페이스를 상속 받을 때, A와 B는 run() 이라는 메소드명이 같고 매개변수 형식도 동일한 메소드가 있다. 이때 run() 메소드에서 충돌이 일어나면서 컴파일 에러가 발생하게 되는 것이다.

  • 인터페이스 상속 구조에서 서브 인터페이스는 수퍼 인터페이스의 메소드까지 모두 구현해야 한다.
  • 인터페이스 레퍼런스는 인터페이스를 구현화한 클래스의 인스턴스를 참조하는 것이 가능하며 해당 인터페이스에 선언된 메소드만 호출이 가능하다.
  • 인터페이스는 Object가 최상위 부모가 아니다.


인터페이스의 기본 메소드 (Default Method)

자바 8부터는 인터페이스에 기본 메소드(default method)가 추가되었다. 이 메소드가 추가된 배경을 다음과 같다. A라는 인터페이스를 구현화하고 있는 클래스들은 A의 추상 메소드들을 모두 구현화해야한다 그런데 만약에 A 인터페이스에 새로운 메소드가 추가되었다고 생각해보자 그러면 이 A를 구현화하는 모든 클래스들에서 해당 메소드를 구현화하는 작업이 필요한 것이다. 때문에 인터페이스에 새로운 메소드를 추가한다는 것은 굉장히 부담스러운 일이다. 이를 보완하기 위해 나타난 것이 기본 메소드이며 기존 인터페이스에서 선언하던 추상 메소드와 다르게 default 키워드를 앞에 붙여서 사용하여 선언하며 일반 메소드처럼 구현부가 있어야 한다.

사용 예시

public interface Foo {

  default void print() {
    System.out.println("default method!");
  }
  
}

주의사항

  • 해당 interface의 구현체들은 default method가 어떻게 구현되었는지 알 수 없다.
  • default method의 기능사항이 제대로 동작할 것이란 보장할 수 없다.
  • 문제 발생시 RuntimeException이 발생할 수 있다.
  • default method 사용시 문서화를 잘 하는 것이 중요.
  • default method를 재정의가 가능하나 위와 같은 문제점이 발생할 여지가 높으며, 사용 시 이 또한 문서화를 잘 남기는 것이 중요.


인터페이스의 static 메소드

자바8 부터 static 메소드가 추가 되었다. 재정의(오버라이딩)이 가능하던 기본 메소드와는 다르게 static 메소드는 오버라이딩이 불가하며 객체의 인스턴스화 없이도 해당 메소드 사용이 가능하다.

interface Test {

  static void running(String name) {
    System.out.println(name + "을 실행중..");
  }
  
}


인터페이스의 private 메소드

자바9 부터 인터페이스에 private 메소드와 private static 메소드가 추가되었다.

추가된 배경

  • 여전히 자바8 에서의 기본 메소드와 static 메소드가 있음에도 불편한 점이 있어서
  • 특정 기능만 수행하는 내부 메소드인데, 외부에 공개되는 public method로 만들어야 되기 때문
  • 코드의 중복을 줄이고 interface에 대한 캡슐화를 유지하는 것이 가능해짐

private 메소드 규칙

  • private 메소드는 구현부를 가져야만 한다.
  • 오직 인터페이스 내부에서만 사용할 수 있다.
  • private static 메소드는 다른 static메소드 와 static이 아닌 메소드에서도 사용이 가능하다.
  • static이 아닌 private 메소드는 다른 private static에서는 사용될 수 없다.

사용 예시

interface Tester {
  
  private void run() {
    System.out.println("private 메소드!");
  }
  
  private static void running() {
    run();
    System.out.println("private static 메소드");
  }
  
}

추가적으로 다음 내용에 대하여 학습해도 좋을 것 같다.

강한 결합과 느슨한 결합에 대한 비교, 아직 이 내용이 이해가 명확하게 되지는 않아서 자주 보고 확실히 짚고 넘어가야 겠다.

참고 블로그





참고

profile
만사가 귀찮은 ISFP가 쓰는 학습 블로그

0개의 댓글