추상클래스의 일종으로, '추상메서드'와 '상수'만을 멤버로 가질 수 있다.
➡️ 그래서 추상클래스보다 추상화의 정도가 높다.
➡️ 추상클래스를 미완성된 설계도라고 한다면, 인터페이스는 밑그림만 그려져 있는 설계도이다.interface 인터페이스 이름{ public static final 타입 상수이름 = 값; public abstract 반환타입 메서드이름(매개변수); }
interface PlayingCard{ public static final int SPADE = 4; final int DIAMIOND = 3; static int HEART = 2; int CLOVER = 1; public abstract String getCardNumber(); String getCardKind(); // 컴파일러가 알아서 생략된 부분을 추가해준다. }
🔸 인터페이스 : 아무것도 없이 추상메서드'만' 가지고 있는 클래스(멤버변수 X)
🔸 추상클래스 : 일반클래스이지만 추상메서드'를' 가지고 있는 클래스(멤버변수 O)
🔸 모든 멤버변수는 public static final이어야 한다.(생략가능)
🔸 모든 메서드는 public abstract이어야 한다.(생략 가능하지만, static메서드와 default메서드는 예외)
➡️ 인터페이스는 무조건 상수와 추상메서드만 가질 수 있기때문에 public static final과 public abstract를 생략할 수 있다. 위의 제어자가 없어도 컴파일러가 자동으로 추가해준다.
🔸 인터페이스는 인터페이스로부터만 상속받을 수 있다.(다중상속 가능)
interface Movable{ void move(int x, int y); } interface Attackable{ void attack(Unit unit); } interface Fightable extends Movable, Attackable{ ... }
🔸 인터페이스도 추상클래스와 같이 그 자체로 인스턴스를 생성할 수 없고, implements키워드를 사용하여 구현하는 클래스를 작성해야 한다.
🔸 인터페이스의 이름은 주로 'able'로 끝난다.
🔸 만약 인터페이스의 메서드 중 일부만 구현한다면 abstract를 사용하여 추상클래스로 선언해야한다.class 클래스이름 implements 인터페이스이름{ /* 추상메서드 구현 */ }
class Unit{ int HP; int x; int y; } class Fighter extends Unit implements Fightable{ public void move(int x, int y){/* 이동하기 */}; public void attack(Unit u){/* 공격하기 */} }
class Test{ public static void main(String args[]){ Unit unit = new Unit(); Fighter f = new Fighter(); f.attack(unit); } }
🔸 상속관계
Fighter ➡️ Unit ➡️ Object
➡️ Fightable ➡️ Movable
➡️ Attackable
☑️ 조상타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있다.
🔸 인터페이스와 인터페이스를 구현한 클래스의 관계도 조상-자손 관계라고 볼 수 있다.Fightable f = (Fightable) new Fighter(); // Fightable f = new Fighter(); // Unit unit = new Fighter(); 도 가능
여기서 참조변수 f는 Fightable인터페이스에 정의된 메서드만 호출 가능하다.
void attack(Fightable f){ ... }
🔸 인터페이스 Fightable을 구현한 클래스들의 인스턴스만 매개변수로 받을 수 있다.
➡️ 그래서 매개변수를 넘겨줄 때 Fightable을 구현한 클래스의 인스턴스를 넘겨줘야 한다.class Fighter extends Unit implements Fightable{ public void move(int x, int y){/* 이동하기 */}; public void attack(Fightable f){/* 공격하기 */} }
🔸 리턴타입을 인터페이스로 가지는 메서드 : 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다.
Fightable method(){ ... Fighter fighter = new Fighter(); return fighter; }
interface Parseable{ public abstract void parse(String fileName); } class XMLParser implements Parseable{ public void parse(String fileName){ ... } } class HTMLParser implements Parseable{ public void parse(String fileName){ ... } } class ParseManager{ public static Parseable getParser(String type){ if(...){ ... return new XMLParser; }else{ ... return new HTMLParser; } } }
class Test{ public static void main(String args[]){ Parseable p = new ParseManager.getParser("XML"); p.parse("doc.xml"); } }
- 개발시간을 단축시킬 수 있다.
➡️ 메서드를 호출할 때는 선언부만 알면되기 때문에 인터페이스를 구현하는 클래스가 완성될 때까지 기다리지 않고 개발을 진행할 수있다.- 표준화가 가능하다.
➡️ 프로젝트의 틀을 인터페이스로 만든 후, 인터페이스를 구현한다면 일관성 있고 정형화된 프로그램을 개발할 수 있다.- 서로 관계가 없는 클래스들도 관계를 맺을 수 있다.
➡️ 전혀 관계가 없는 클래스들을 공통된 인터페이스를 하나 만들어서 구현함으로써 관계를 맺을 수 있다.- 독립적인 프로그래밍이 가능하다.
➡️ 클래스 간의 직접적인 관계가 아닌 간접적인 관계를 통해서, 한 클래스의 변경이 다른 클래스에 영향을 미치지 않을 수 있다.interface I{ public abstract void play(); } class A{ void autoPlay(I i){ i.play(); } } class B implements I{ public void play(){ ... } } class C implements I{ public void play(){ ... } } class Test{ public static void main(String args[]){ A a = new A(); a.autoPlay(new B()); a.autoPlay(new C()); } }
➡️ class A 는 구현된 클래스들(class B, class C)에 대해서는 전혀 몰라도 상관없다. 매개변수로 받는 인터페이스 I의 영향만 받는다. (A - I - B, C)
A와 B,C는 간접적인 관계에 있다.(B와 C의 메서드를 호출하지만 직접적으로 호출하는 것이 아닌 인터페이스 I를 구현한 클래스의 인스턴스를 매개변수로 호출이 되는 것이기 때문)