JAVA 인터페이스

Dev.Shinny·2022년 9월 27일
0

자바의 정석

목록 보기
10/18

인터페이스란?

추상 메서드의 집합이다.
다중 상속처럼 사용할 수 있다.

오직 추상메서드상수만을 멤버로 가질 수 있으며, 그 외의 다른 어떤한 요소도 허용하지 않는다.

추상클래스가 '미완성 설계도'라고 한다면, 인터페이스는 밑그림만 그려져 있는 '기본 설계도'라 할 수 있다. (모든 멤버가 public이다.)

인터페이스도 추상 클래스처럼 그 자체로는 인스턴스를 생성할 수 없으며, 자신에 정의된 추상 메서드의 몸통을 만들어주는 클래스를 작성해야 한다. 구현하는 인터페이스의 메서드 중 일부만 구현한다면, abstract를 붙여서 추상클래스로 선언해야 한다.

접근제어자 interface 인터페이스명 {
	public static final 타입 상수이름 =;
    public abstract 반환타입 메서드명(매개변수)
}

class 클래스명 implements 인터페이스명{
	...
}
  • 모든 멤버변수는 public static final이어야 하며, 생략할 수 있다.
  • 모든 메서드는 public abstract이어야 하며, 이를 생략할 수 있다.

상속과 인터페이스

상속과 인터페이스를 동시에 사용하며 다중 상속과 같은 효과를 낼 수 있다.

접근제어자 interface 인터페이스명 {
	...
}
접근제어자 class 클래스명 {
	...
}
class 클래스명 extends 클래스명 implements 인터페이스명 {
	...
}

인터페이스의 상속

인터페이스는 인터페이스로부터만 상속받을 수 있으며, 클래스와는 달리 다중상속, 즉 여러개의 인터페이스로부터 상속을 받는 것이 가능하다. 인터페이스의 다중상속이 가능한 이유는 추상메서드는 충돌해도 문제가 없기 때문이다. 그러나 자바에서 인터페이스로 다중상속을 구현하는 경우는 거의 없다.

인터페이스는 클래스와 달리 Object 클래스와 같은 최고 조상이 없다.

interface 클래스명1 {
	...
}
interface 클래스명2 {
	...
}	
interface 클래스명3 extends 클래스명1, 클래스명2 {
	...
}

인터페이스의 다형성

인터페이스 역시 인터페이스 타입의 참조변수로 이를 구현한 클래스의 인스턴스를 참조할 수 있으며, 인터페이스 타입의 형변환도 가능하다. 형변환되는 경우 인터페이스에 선언된 메서드만을 사용 가능하다.

인터페이스는 메서드의 매개변수 타입으로 사용될 수 있다. 인터페이스 타입의 매개변수가 갖는 의미는 메서드 호출 시 해당 인터페이스를 구현한 클래스의 인스턴스를 매개변수로 제공해야한다는 것이다.

void test ( inter i ) {
	...
}

test 메서드를 호출할 때는 매개변수로 inter 인터페이스로 구현한 클래스의 인스턴스를 넘겨주어야 한다.

인터페이스를 메서드의 리턴타입으로 지정할 수 있다.

Fightable method(){
	...
    (1)
 	Fighter f = new Fighter();
    return f; // f의 타입은 Fighter지만 Fightable로 형변환이 가능하기 때문에 타입이 일치한다.
    (2)
    return new Fighter();
}

class Fighter extends Unit implements Fightable{
	public void move(int x, int y) {...}
    public void attack(Fightable f) {...}
}

(1)과 (2)는 같은 코드이다. 리턴타입이 인터페이스라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미한다.

인터페이스 장점

  • 개발시간을 단축시킬 수 있다.
  • 표준화가 가능하다.
  • 서로 관계 없는 클래스에게 관계를 맺어줄 수 있다.
  • 독립적인 프로그래밍이 가능하다.
  1. 개발시간을 단축시킬 수 있다.
    동시에 다른 한 쪽에서 인터페이스를 구현하는 클래스를 작성하게 하면, 인터페이스를 구현하는 클래스가 작성될 때까지 기다리지 않고도 양쪽에서 동시에 개발을 진행할 수 있다.

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

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

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

(1) 직접적인 관계의 A-B 클래스
class A {
	public void methodA(B b){
    	b.methodB();
    }
}

class B{
	public void methodB() {
    	System.out.println("methodB()");
    }
}

class InterfaceTest{
	public static void main(String args[]){
    	A a = new A();
        a.methodA(new B());
   	}
}

(2) 간접적인 관계의 A-B 클래스
class A {
	public void methodA(I i){
    	i.methodB();
    }
}

interface I {
	void methodB (); 
}

class B implements I {
	public void methodB() {
    	System.out.println("methodB()");
    }
}

인터페이스의 이해

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

앞 서 작성된 코드 (2)를 보면 클래스 A와 B는 직접적인 'A-B'에서 'A-I-B'의 간접적인 관계로 바뀌었다.

결국 클래스 A는 여전히 클래스 B의 메서드를 호출하지만, 클래스 A는 인터페이스 I하고만 직접적인 관계에 있기 때문에 클래스 B의 변경에 영향을 받지 않는다.

클래스 A는 인터페이스를 통해 실제로 사용하는 클래스의 이름을 몰라도 되고 심지어는 실제로 구현된 클래스가 존재하지 않아도 문제되지 않는다. 클래스 A는 오직 직접적인 관계에 있는 인터페이스 I의 영향만 받는다.

인터페이스 I는 실제구현 내용(클래스 B)을 감싸고 있는 껍데기이며, 클래스 A는 껍데기 안 어떤 알맹이(클래스)가 들어 있는지 몰라도 된다.

디폴트 메서드와 static 메서드

JDK1.8부터 디폴트 메서드와 static 메서드도 추가할 수 있게 되었다. static 메서드는 인스턴스와 관계가 없는 독립적인 메서드이기 추가하지 못 할 이유가 없다.

디폴트 메서드

인터페이스에 메서드를 추가한다는 것은, 추상 메서드를 추가한다는 것이고, 이 인터페이스를 구현한 기존의 모든 클래스들이 새로 추가된 메서드를 구현해야한다는 것을 의미한다.

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

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

디폴트 메서드는 앞에 키워드 default를 붙이며, 추상 메서드와 달리 일반 메서드처럼 몸통{}이 있어야 한다. 디폴트 메서드 역시 접근 제어자는 public이며 생략할 수 있다.

  1. 여러 인터페이스의 디폴트 메서드 간 충돌
    : 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩
  2. 디폴트 메서드와 부모 클래스의 메서드 간 충돌
    : 부모 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.

그냥 필요한 쪽의 메서드와 같은 내용으로 오버라이딩 해버리면 그만이다.

profile
Hello I'm Shinny. A developer who try to enjoy the challenge.

0개의 댓글