[자바] 인터페이스
- 일종의 추상클래스이다. ( 추상 클래스 보다 추상화가 더 되어 있다. )
- 오직 추상 메서드와 상수만 멤버로 갖는다
어떤 클래스가 있고 인터페이스 사용시 그 클래스는 반드시 인터페이스에 있는 메소드를 사용하게끔 강제한다.
interface I {
public void z(); // 구현부 (몸통) 이 없어야 한다
}
class A implements I {
public void z(){} // 구현은 여기서 한다.
}
인터페이스 규칙
1. 하나의 클래스는 복수개의 인터페이스 구현 가능
interface I1 {
public void x(); // 구현 ㄴ
}
interface I1 {
public void z();
}
class A implements I1, I2 {
public void x() {} // 구현필수
public void z() {} // 구현필수
}
2. 인터페이스도 상속이 된다
interface I3 {
public void x(); // 구현 ㄴ
}
interface I4 extends I3 {
public void z();
}
class A implements I4 {
public void x() {} // 구현필수
public void z() {} // 구현필수
}
3. 인터페이스의 멤버는 public 이여야만 한다
인터페이스 작성방식
interface 인터페이스이름 {
public static final 타입 상수이름 = 값;
public abstract 메서드이름(매개변수 목록);
}
- 모든 멤버변수는 public static final ( 생략가능 ) - 접근제어자 public 명심
- 모든 메서드는 public abstract ( 생략가능 ) - 접근제어자 public 명심
- 인터페이스는 다중 상속이 가능하다.
인터페이스 구현
- 인터페이스는 자체로 인스턴스를 생성할 수 없다.
추상 클래스가 상속을 통해 추상 메서드를 완성하듯 implements를 통해 클래스 작성
class 클래스 이름 implements 인터페이스이름 { }
class Fighter implements Fightable {
public void move(int x, int y) { /* */ }
public void attack(Unit u) { /* */ }
}
만일, 인터페이스의 메서드 중 일부만 구현하면 abstract 붙여줘야 한다.
abstract class Fighter implements Fightable {
public void move(int x, int y) { /* */ }
}
상속과 구현을 동시에 할 수 있다.
class Fighter extends Unit implements Fightable {
public void move(int x, int y) { /* */ }
public void attack(Unit u) { /* */ }
}
인터페이스를 이용한 다형성
인터페이스도 이를 구현한 클래스의 조상이라 할 수 있으므로 해당 인터페이스 타입의 참조변수로 이를 구현한 클래스의 인스턴스를 참조가능하고, 인터페이스의 타입으로 형변환도 가능하다.
인터페이스 Fightable을 클래스 Fighter가 구현했을때
Fightable f = new Fighter();
// Fightable 이라는 인터페이스
// Fighter 이라는 클래스
메서드의 매개변수의 타입도 가능
void attack(Fightable f) { }
인터페이스 타입의 매개변수가 갖는 의미는 인터페이스를 구현한 클래스의 인스턴스를 매개변수로 제공해야한다는것이다
Fiahtable method() {
Fighter f = new Fighter();
return f;
// 위의 두줄을 윗말대로 줄여보면
// return new Fighter(); // 인스턴스를 반환하고 있다
}
class Fighter extends Unit implements Fightable {
void attack(Fightable f) { }
}
정말 중요한것!
Fightable method() {
Fighter f = new Fighter();
return f;
}
리턴 타입이 인터 페이스라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미한다.
interface Parseable {
public static void parse(String fileName);
}
class ParserManager {
// 리턴타입이 Parseable 인터페이스이다.
public static void main(String[] args) {
if( type.equals("XML")) {
return new XMLParser();
} else {
Parseable p = new HTMLParseable();
return p;
}
}
}
class XMLParser implements Parseable {
public void parse(String fileName) {
System.out.println(fileName);
}
}
class HTMLParser implements Parseable {
public void parse(String fileName) {
System.out.println(fileName);
}
}
class ParserTest {
public static void main(String[] args) {
Parseable parser = ParserManager.getParser("XML");
parser.parse("xml");
parser = ParserManager.getParser("HTML");
parser.parse("html");
}
]
getParser 매서드는 매개변수로 넘겨받는 type에 따라 값이 XMLParser 인스턴스 또는 HTMLParser 인스턴스 반환한다
이렇게 하면, 프로그램 자체를 변경하지 않고, 서버측의 변경만으로 사용자가 새로 개전된 프로그램을 사용할 수 있다.
인터페이스 이해
직접적인 관계
A( User ) -> B ( Provider ) : 직접적인 관계 , B가 바뀌면 A도 바뀌어야함
class A {
public void method(B b) {
b.methodB();
}
}
class B {
public void method() {
System.out.println("method b");
}
}
class InterfaceTest {
public static void main(String[] args) {
A a = new A();
a.methodA(new B());
}
}
간접적인 관계로 바꾸기 위해서는 인터페이스를 통해 클래스 B의 선언과 구현 분리 필요
간접적으로 'A-I-B' 관계 : A는 인터페이스의 영향만 직접적으로 받는다 ( B의 영향을 받지 않는다.)
class A {
public void method(I i) { // 이 부분이 중요
i.methodB(); // 이 부분이 중요
}
}
interface I {
public abstract void methodB();
}
class B implements I {
public void method() {
System.out.println("interface method b");
}
}
class InterfaceTest {
public static void main(String[] args) {
A a = new A();
a.methodA(new B());
}
}
인스턴스를 직접 생성하지 않고, getInstance() 라는 메서드를 통해 제공 받는다
나중에 다른 클래스의 인스턴스로 변경되어도 A클래스의 변경없이 getInstance()만 변경하면 된다는 장점이 있다
class InterfaceTest {
public static void main(String[] args) {
A a = new A();
a.methodA();
}
}
class A {
void method() {
I i = InstanceManager.getInstance();
i.methodB();
System.out.println(i.toString());
}
}
interface I {
public abstract void methodB();
}
class B implements I {
public void method() {
System.out.println("interface method b");
}
public String toString() { return "class B" }
}
class InstanceManager {
public static I getInstace() {
return new B(); // 다른 인스턴스로 바꾸려면 여기만 바꾸면 된다
}
}
인터페이스 I 타입의 참조변수 i로도 Object 클래스에 정의된 메서들을 호출 가능하다 ( toString() 이런 메서드 )