인터페이스는 객체의 사용방법을 정의한 타입입니다. 인터페이스를 통해 다양한 객체를 동일한 방법으로 이용할 수 있습니다.
인터페이스는 개발 코드와 객체가 서로 통신하는 접점 역할을 합니다. 개발 코드가 인터페이스의 메소드를 호출하면 인터페이스는 객체의 메소드를 호출합니다. 그렇기 때문에 개발 코드는 객체의 내부 코드를 알 필요가 없고 인터페이스의 메소드만 알고 있으면 됩니다.
1. 인터페이스를 사용하는 이유
개발 코드를 수정하지 않고 사용하는 객체를 변경할 수 있도록 하기 위해서입니다. 인터페이스는 하나의 객체가 아니라 여러 객체들과 사용이 가능하므로 어떤 객체를 사용하느냐에 따라 실행 내용과 리턴값이 달라질 수 있습니다. 따라서 개발 코드 측면에서는 코드 변경 없이 실행 내용과 리턴값을 다양화할 수 있다는 장점을 가지게 됩니다.
2. 인터페이스 선언
인터페이스는 '~.java' 형태의 소스 파일로 작성되고 컴파일러를 통해 '~.class' 형태로 컴파일되기 때문에 물리적 형태는 클래스와 동일합니다. 그러나 소스를 작성할 때 선언하는 방법이 다릅니다.
[public] interface 이름 {...}
인터페이스 이름은 클래스 이름을 작성하는 방법과 동일하게 첫글자를 대문자로 작성합니다. 또한 public 접근 제한자를 통해 다른 패키지에서도 인터페이스를 사용할 수 있게 해줍니다.
이클립스에서는 인터페이스를 생성하고자 하는 패키지를 우클릭한 후 new를 클릭한 후 인터페이스를 생성하면 자동으로 인터페이스를 생성해줍니다.
인터페이스는 상수 필드(public static final)와 추상 메소드만을 구성 멤버로 가집니다. 인터페이스는 객체로 생성할 수 없기 때문에 생성자를 가질 수 없습니다. 인터페이스의 필드에 public static final을 생략하더라도 컴파일 과정에서 자동으로 붙게 됩니다. 상수 이름은 모두 대문자로 작성하되, 서로 다른 단어로 구성될 경우 언더바로 연결하는 것이 관례입니다. 인터페이스 상수는 반드시 선언과 동시에 초기값을 지정해야 합니다.
인터페이스의 메소드는 최종적으로 객체에서 실행됩니다. 인터페이스에 선언된 추상 메소드는 모두 public abstract의 튻성을 갖기 때문에 이를 생략하더라도 컴파일 과정에서 자동으로 붙게 됩니다.
3. 인터페이스의 구현
개발 코드가 인터페이스 메소드를 호출하면 인터페이스는 객체의 메소드를 호출합니다. 객체는 인터페이스에서 정의된 추상 메소드를 재정의한 실체 메소드를 가지고 있어야 합니다. 이러한 객체를 인터페이스의 구현(implement) 객체라고 하고, 구현 객체를 생성하는 클래스를 구현 클래스라고 합니다.
구현 클래스
구현 클래스는 보통의 클래스와 동일한데, 인터페이스 타입으로 사용할 수 있음을 알려주기 위해 클래스 선언부에 'implements' 키워드를 추가하고 인터페이스 이름을 명시해야 합니다. 그리고 인터페이스에 선언된 추상 메소드의 실체 메소드를 선언해야 합니다.
public class 구현클래스이름 implements 인터페이스이름 { //인터페이스에 선언된 추상 메소드의 실체 메소드 선언 } |
구현 클래스가 작성되면 new 연산자로 객체를 생성할 수 있습니다. 하지만 다음 코드는 인터페이스를 사용한 것이 아닙니다.
Television(구현클래스) tv = new Television();
인터페이스로 구현 객체를 사용하려면 다음과 같이 인터페이스 변수를 선언하고 구현 객체를 대입해야 합니다. 인터페이스 변수는 참조 타입이기 때문에 구현 객체가 대입될 경우 구현 객체의 번지를 저장합니다.
인터페이스 변수 = 구현객체;
다중 인터페이스 구현 클래스
다중의 인터페이스가 한 객체의 메소드를 호출할 수 있기 위해서는 객체가 다중의 인터페이스를 모두 구현해야 합니다.
public class 구현클래스이름 impliments 인터페이스A, 인터페이스B { //인터페이스 A에 선언된 추상 메소드의 실체 메소드 선언 //인터페이스 B에 선언된 추상 메소드의 실체 메소드 선언 } |
위의 경우 인터페이스 변수에 구현 객체를 각각 대입할 수 있습니다.
4. 인터페이스 사용
개발 코드는 인터페이스에 선언된 추상 메소드를 호출하고, 인터페이스는 구현 객체의 재정의 메소드를 호출합니다.
클래스를 선언할 때 인터페이스는 필드, 생성자 또는 메소드의 매개변수, 생성자 또는 메소드의 로컬변수로 선언될 수 있습니다.
- 인터페이스가 필드 타입으로 사용될 경우: 필드에 구현 객체 대입 가능
- 인터페이스가 생성자의 매개변수 타입으로 사용될 경우: new 연산자로 객체를 생성할 때 구현 객체를 생성자의 매갯값으로 대입 가능
- 인터페이스가 로컬 변수 타입으로 사용될 경우: 변수에 구현 객체 대입 가능
- 인터페이스가 메소드의 매개변수 타입으로 사용될 경우: 메소드 호출 시 구현 객체를 매개 값으로 대입할 수 있습니다.
다음 예제에서는 메소드의 매개변수로 인터페이스가 들어갈 때, 그 자리에 구현 객체를 대입함으로써 메소드를 호출할 수 있음을 보여줍니다.
5. 구현 객체 타입 변환
구현 객체가 인터페이스 타입으로 자동 타입 변환하면, 인터페이스에 선언된 메소드만 사용 가능하다는 제약 사항이 따릅니다. 하지만 경우에 따라서는 구현 클래스에 선언된 필드와 메소드를 사용해야 할 때도 있습니다. 이때 강제 타입 변환을 통해 다시 구현 클래스 타입으로 변환한 다음 구현 클래스의 멤버를 사용할 수 있게 됩니다. 인터페이스 타입의 강제 변환 시에도 상속의 경우와 마찬가지로 instanceof 연산자를 통해 타입을 확인할 수 있습니다.
6. 인터페이스 상속
인터페이스도 다른 인터페이스를 상속할 수 있습니다. 인터페이스는 클래스와는 달리 다중 상속을 허용합니다.
public interface 하위인터페이스 extends 상위인터페이스1, 상위인터페이스2 {...}
하위 인터페이스를 구현하는 클래스는 하위 인터페이스의 메소드뿐만 아니라 상위 인터페이스의 모든 추상 메소드에 대한 실체 메소드를 가지고 있어야 합니다. 그렇기 때문에 구현 클래스로부터 객체를 생성한 이후에 다음과 같이 하위 및 상위 인터페이스 타입으로 변환이 가능합니다.
하위인터페이스 변수 = new 구현클래스(...);
상위인터페이스1 변수 = new 구현클래스(...);
상위인터페이스2 변수 = new 구현클래스(...);
하위 인터페이스로 타입 변환이 되면 상위 및 하위 인터페이스에 선언된 모든 메소드를 사용할 수 있으나, 상위 인터페이스로 타입 변환되면 상위 인터페이스에 선언된 메소드만 사용 가능하고 하위 인터페이스에 선언된 메소드는 사용할 수 없습니다.
'java' 카테고리의 다른 글
java 익명 객체 - 중첩 클래스와 중첩 인터페이스 (0) | 2021.01.26 |
---|---|
java 중첩 클래스, 중첩 인터페이스 (0) | 2021.01.26 |
추상 클래스, 추상 메소드 (0) | 2021.01.25 |
다형성 (0) | 2021.01.25 |
메소드 재정의(오버라이딩 Overriding) (0) | 2021.01.24 |