[JAVA] 인터페이스

Coastby·2022년 9월 28일
0

LIKELION Back-End School

목록 보기
21/61

○ 인터페이스란?

💡 인터페이스 : 표준, 강제, 클래스간 유사성

인터페이스는 일종의 추상클래스이며, 추상메서드와 상수만을 포함하며 다른 클래스를 작성하는데 도움 줄 목적으로 작성된다.

인터페이스 구조

키워드로 class 대신 interface를 사용한다. 접근제어자로 public, default도 사용 가능하다.

인터페이스 이름에는 주로 ~able로 끝나는 것들이 많다. 이는 어떠한 기능 또는 행위를 하는데 필요한 메서드를 제공한다는 의미를 강조한다.

interface 인터페이스이름 {
	(public static final) 타입 상수이름 =;		//값이 대입되어야 한다.
    (public abstract) 메서드이름(매개변수);
}
  • 모든 멤버변수는 public static final이어야 하며, 이를 생략할 수 있다.
  • 모든 메서드는 public abstract여야 하며, 이를 생략할 수 있다.
  • 단, JDK1.8부터 static 메서드와 디폴트 메서드 사용 가능
    인터페이스에 정의된 모든 멤버에 적용되기 때문에 제어자를 생략할 수 있으며, 편의상 생략한다. 생략된 제어자는 컴파일러가 자동으로 추가해준다.

인터페이스 상속

인터페이스는 인터페이스를 상속 받을 수 있으며, 여러 인터페이스를 상속받는 다중 상속이 가능하다.

인터페이스의 구현

인터페이스도 참조변수 선언은 가능하지만 인스턴트 생성을 할 수 없다. 인터페이스는 자신에 정의된 추상메서드를 구현할 클래스가 필요하며, 이 클래스는 구현한다는 의미의 키워드 implements를 사용한다.

class 클래스이름 implements 인터페이스이름 {
	// 인터페이스에 정의된 추상메서드를 구현해야 한다.
}

//상속과 구현을 같이 할 수도 있다
class 클래스이름 extends 부모클래스이름 implements 인터페이스이름 {
	// 인터페이스에 정의된 추상메서드를 구현해야 한다.
}

오버라이딩할 때는 조상의 메서드보다 넓은 범위의 접근 제어자를 지정해야 한다. 모든 인터페이스의 메서드는 public abstract이므로 구현하는 클래스의 메서드의 접근제어자는 반드시 public이 되어야 한다.

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

'자바도 인터페이스를 이용하면 다중상속이 가능하다'라고 하는 것일 뿐 자바에서 인터페이스로 다중상속을 구현하는 경우는 거의 없다.

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

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

Fightable f = (Fightable) new Fighter ();
Fightable f = 			  new Fighter();

그리고 함수의 매개변수 또는 리턴 타입으로 인터페이스 타입을 사용할 수도 있다.

interface Fightable {
	...
    void attack (Fightable f);
}

class FighterManager {
	public static Fightable getFighter (String type) {
    	if (type.equals("lv1")) {
        	Fighter f = new Fighter();
        	return f;		// = return new Fighter();
        } else {
        	Boss b = new Boss();
            return b;		// = return new Boss();
        }
    	
    }
}

class Fighter implements Fightable {
	...
    public void attack (Fightable f) {
    	/* 공격하는 코드 */
        System.out.println("공격");
    }
}

class Boss implements Fightable {
	...
    public void attack (Fightable f) {
    	/* 공격 세게하는 코드 */
        System.out.println("세게 공격");
    
    }
}

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

Fightable 인터페이스는 공격 기능 구현을 목적으로 attack()을 정의했다. 그리고 Fighter와 Boss 클래스에서 인터페이스를 구현하였다.
FightManager의 getFigher를 이용해 매개변수의 값에 따라 Fighter 또는 Boss의 인스턴스를 반환받을 수 있다. 즉, 필요에 따라 같은 목적의 다른 기능을 하는 인스턴스를 사용할 수 있다.

public class InterfacePrac {

    public static void main(String[] args) {
        Fightable a = new Fighter();
        Fightable f = FighterManager.getFighter("lv1");
        f.attack(a);
        Fightable g = FighterManager.getFighter("lv100");
        g.attack(a);
    }

}

//result
공격
세게 공격

만일 나중에 새로운 Fighter가 나오면 main 메서드 변경없이 getFighter만 변경하면 된다.

이러한 장점은 특히 분산환경 프로그래밍에서 그 위력을 발휘한다. 사용자 컴퓨터에 설치된 프로그램을 변경하지 않고 서버측의 변경만으로도 사용자가 새로 개정된 프로그램을 사용하는 것이 가능하다.

인터페이스의 장점

1. 개발 시간을 단축시킬 수 있다.
일단 인터페이스가 작성되면
1) 메서드를 호출하는 쪽에서는, 메서드의 내용에 관계없이 선언부만 알면된다.
2) 인터페이스를 구현하는 클래스를 작성하는 쪽에서는, 인터페이스를 구현하는 클래스가 작성될 때까지 기다리지 않고도
양쪽에서 동시에 개발을 진행할 수 있다.

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

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

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

Ex) 데이터베이스 관련 인터페이스 : 스프링 게시판 구현에서 repository interface를 작성하고, 데이터 접근 방법을 바꿔낄 수 있게 한다.

💡 인터페이스 이해

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

디폴트 메서드와 static 메서드

JDK 1.8부터는 디폴트 메서드와 static 메서드도 추가할 수 있게 되었다.

java.util.Collection 인터페이스가 있는데 이 인터페이스와 관련된 static 메서드들이 인터페이스에는 추상 메서드만 선언할 수 있다는 원칙 때문에 별도의 클래스, Collections라는 클래스에 들어가게 되었다. 만일 인터페이스에 static 메서드를 추가할 수 있었다면, Collections 클래스는 존재하지 않았을 것이다.

디폴트 메서드 (default method)

  • 인터페이스가 변경되지 않으면 제일 좋겠지만, 아무리 설계를 잘해도 언젠가 변경은 발생하기 마련이다.
  • 디폴트 메서드는 추상 메서드의 기본적인 구현을 제공하는 메서드로, 추상 메서드가 아니기 때문에 디폴트 메서드가 추가되어도 해당 인터페이스를 구현한 클래스를 변경하지 않아도 된다.
  • 디폴트 메서드는 앞에 키워드 default를 붙이며, 추상 메서드와 달리 일반 메서드처럼 몸통 {}이 있어야 한다. 디폴트 메서드 역시 접근 제어자가 public이며, 생략가능하다.
  • 디폴트 메서드가 기존 메서드와 이름이 중복되어 충돌하는 경우가 발생한다. 이 충돌을 해결하는 규칙은 다음과 같다.
    • 여러 인터페이스의 디폴트 메서드 간의 충돌
      : 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩해야 한다.
    • 디폴트 메서드와 조상 클래스의 메서드 간의 충돌
      : 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.
    • (필요한 쪽의 메서드와 같은 내용으로 오버라이딩 하면 된다.)
profile
훈이야 화이팅

0개의 댓글