JAVA/JAVA 기본정리

인터페이스(interface)

hyun-1200 2022. 6. 10. 15:30

📌 인터페이스 (interface)

: 인터페이스는 일종의 추상클래스이다. 오직 추상메서드와 상수만을 멤버로 가질 수 있으며, 그 외 다른 요소는 허용하지 않는다.

 

  • 추상클래스를 부분적으로만 완성된 '미완성 설계도'라고 한다면,
  • 인터페이스는 구현된 것은 아무것도 없고 밑그림만 그려져 있는 '기본설계도'라 할 수 있다. 

인터페이스 작성방법 

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

- 접근제어자로 public 또는 default를 사용할 수 있다. 

 

인터페이스 제약사항 

더보기

1. 모든 멤버변수는 public static final이어야 하며, 생략할 수 있다.

2. 모든 메서드는 public abstract이어야 하며, 생략할 수 있다. 

( 단, JDK 1.8부터  static 메서드와 디폴트 메서드의 추가를 허용한다. ) 

- 원래는 인터페이스의 모든 메서드는 추상메서드이어야 하는데, JDK 1.8부터 인터페이스에 static 메서드와 디폴트 메서드 추가를 허용했다. JDK 1.8 이전과 이후의 규칙을 모두 알고 있어야 한다. 

  • 인터페이스에 정의된 모든 멤버에 예외없이 적용되는 사항이기 때문에 제어자를 생략할 수 있으며, 생략된 제어자는 컴파일 시에 컴파일러가 자동으로 추가해준다. 

 


📌 인터페이스의 상속 

- 인터페이스는 인터페이스로부터만 상속받을 수 있으며, 클래스와 달리 다중상속이 가능하다. 

 

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

interface Attackable{
	void attack(Unit u);
}

interface Fightable extends Movable, Attackable{
..
}

 


📌 인터페이스의 구현

  • 인터페이스도 추상클래스처럼 그 자체로는 인스턴스를 생성할 수 없다.
  • 인터페이스는 자신에 정의된 추상메서드의 몸통을 만들어주는 클래스를 작성해야 하며 ' implements' 를 사용하여 구현한다고 표현한다. 
  • 인터페이스의 이름에는 주로 '~을 할 수 있는'의 의미인 'able'로 끝나는 것이 많다. 그 이유는 어떠한 기능을 하는데 필요한 메서드를 제공한다는 의미를 강조하기 위해서이다. 또한 그 인터페이스를 구현한 클래스는 '~를 할 수 있는' 능력을 갖추었다는 의미이기도 하다. 하지만 반드시 모든 인터페이스의 이름이 'able'로 끝나야 하는 것은 아니다. 
class 클래스이름 implements 인터페이스이름{
	// 인터페이스에 정의된 추상메서드를 구현해야 한다. 
}

 

  •  구현하는 인터페이스의 메서드 중 일부만 구현한다면, abstract를 붙여서 추상클래스로 선언해야 한다.
abstract class Fighter implements Fightable{
	public void move(int x, int y) { // 구현 }
    // public void attack(Unit u) 
}

 

  • 상속과 구현을 동시에 할 수도 있다. 
class Fighter extends Unit implments Fightable{
	public void move(int x, int y) {// 구현 }
    public void attack(Unit u) { //구현 }
 }

- 오버라이딩 할때는 조상의 메서드보다 넓은 범위의 접근제어자를 지정해야 하므로, move 메서드는 public static이 생략된 것이기때문에, 이를 구현할 때는 반드시 public의 접근제어자를 사용해야 한다. 


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

  • 자바는 원래 다중상속을 허용하지 않는다.
    • 두 조상으로부터 상속받는 멤버 중 멤버변수 이름이 같거나 메서드 선언부가 같다면, 자손클래스는 어느조상의 것을 상속받게 되는것인지 알 수가 없다. 다중상속은 장점도 있지만 단점이 더 크다고 판단하였기 때문에 자바에서는 다중상속을 허용하지 않는다. 
  • '자바도 인터페이스를 이용하면 다중상속이 가능하다'라고 말할 수 있지만, 자바에서 인터페이스로 다중상속을 구현하는 경우는 거의 없다. 또한,  인터페이스가 다중상속을 위한 것은 아니다.
  • 인터페이스는 static 상수만 정의할 수 있으므로 조상클래스의 멤버변수와 충돌하는 경우는 거의없고 충돌된다 하더라도 클래스 이름을 붙여서 구분이 가능하다.

 

 만일 두개의 클래스로부터 상속을 받아야 하는 상황이라면, 아래 두가지 방식으로 처리한다. 

 

1. 두 조상클래스 중 비중이 높은 쪽을 선택하고 다른쪽은 클래스 내부에 멤버로 포함시키는 방식으로 처리

2. 필요한 부분을 뽑아서 인터페이스로 만들어 구현.  한쪽을 상속받고 나머지 한쪽은 클래스 내에 포함시켜 내부적으로 인스턴스를 생성해서 사용 

 


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

: 인터페이스 타입의 참조변수로 이를 구현한 클래스의 인스턴스를 참조할 수 있으며, 인터페이스 타입으로의 형변환이 가능하다.

 

- 인터페이스 Fightable을 클래스 Fighter 가 구현했을 때, Fighter인스턴스를 Fightable 타입의 참조변수로 참조하는 것이 가능하다.

Fightable f= (Fightable) new Fighter();
// 또는
Fightable f= new Fighter();

 

  • 인터페이스는 다음과 같이 메서드의 매개변수의 타입으로 사용될 수 있다.
void attack(Fightable f){
...
}
  • 메서드의 리턴타입으로 인터페이스의 타입을 지정할 수 있다.
Fightable method(){
	...
    Fighter f= new Fighter();
    return f; // return new Fighter();
 }

- 리턴 타입이 인터페이스라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환하는 것을 의미한다. 

 


📌 인터페이스의 장점

1. 개발시간을 단축시킬 수 있다.
2. 표준화가 가능하다.
3. 서로 관계없는 클래스를에게 관계를 맺어 줄 수 있다.
4. 독립적인 프로그래밍이 가능하다. 

 

1. 개발시간을 단축시킬 수 있다.

- 일단 인터페이스가 작성되면, 이를 사용해서 프로그램을 작성하는 것이 가능하다. 메서드를 호출하는 쪽에서는 메서드의 내용에 관계없이 선언부만 알면 되기 때문이다. 그리고 동시에 다른 한쪽에서는 인터페이스를 구현하는 클래스를 작성하게 되면, 인터페이스를 구현하는 클래스가 작성될 때까지 기다리지 않고도 양쪽에서 동시에 개발을 진행할 수 있다.

 

2. 표준화가 가능하다.

- 프로젝트에 사용되는 기본 틀을 인터페이스로 작성한 다음, 개발자들에게 인터페이스를 구현하여 프로그램을 작성하도록 함으로써 보다 일관되고 정형화된 프로그램의 개발이 가능하다.

 

3. 서로 관계없는 클래스들에게 관계를 맺어 줄 수 있다.

- 서로 상속관계에 있지도 않고, 같은 조상클래스를 가지고 있지 않은 서로 아무런 관계도 없는 클래스들에게 하나의 인터페이스를 공통적으로 구현하도록 함으로써 관계를 맺어 줄 수 있다.

 

4. 독립적인 프로그래밍이 가능하다.

- 인터페이스를 이용하면 클래스의 선언과 구현을 분리시킬 수 있기 때문에 실제구현에 독립적인 프로그램을 작성하는 것이 가능하다. 클래스와 클래스간의 직접적인 관계를 인터페이스를 이용해서 간접적인 관계로 변경하면, 한 클래스의 변경이 관련된 다른 클래스에 영향을 미치지 않는 독립적인 프로그래밍이 가능하다. 

 


📌 인터페이스의 이해

- 그래서, '인터페이스란 도대체 무엇인가?'

- 인터페이스를 이해하기 위해서는 아래 두가지 사항을 반드시 염두에 두고 있어야 한다.

1. 클래스를 사용하는 쪽(User)과 클래스를 제공하는 쪽(Provider) 이 있다.
2. 메서드를 사용하는 쪽(User)에서는 사용하려는 메서드(Provider)의 선언부만 알면된다. 내용은 몰라도 된다. 

 


📌 static메서드와 디폴트 메서드 

 

static메서드

- 인스턴스와 관계없는 독립적인 메서드이기 때문에 인터페이스에 추가하지 못할 이유가 없었다.

 

디폴트 메서드

- 추상메서드의 기본적인 구현을 제공하는 메서드로, 추상메서드가 아니기 때문에 디폴트 메서드가 새로 추가되어도 해당 인터페이스를 구현한 클래스는 변경하지 않아도 된다. 

- 인터페이스가 변경될 수도 있으므로, 변경되어도 인터페이스를 구현한 클래스에 영향가지 않도록 디폴트 메서드를 사용한다.

 

디폴트 메서드 사용법 

- 메서드 앞에 키워드 default를 붙이며, 접근제어자는 public이고 생략가능하다. 

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