[개체지향] 인터페이스
인터페이스
interface : 접해있는 두 물체나 공간 사이의 경계
- 함수 시그내처(함수 선언)를 인터페이스라 부르기도 함
- 함수 시그내처만 사용하는경우 : 함수 포인터 매개변수는 시그내처만 지정
함수 포인터 매개변수 vs 클래스 매개변수
함수 포인터 매개변수
- 어떤 함수 구현도 받아 줌
- 매개변수와 함수 시그내처와 같을 경우
클래스 매개변수
- 부모 클래스를 상속한 클래스면 다 받아줌
- 그중 다형적 메서드 하나를 호출
- 실질적으로 C의 함수 포인터처럼 작동
- 배보다 배꼽이 더 큼
순수 추상 클래스 = 인터페이스
- 동작만(구현은 빼고) 모아 놓은것
- java C#은 이 특별한 클래스를 위해 interface란 키워드 지원
- C++은 별도의 키워드가 없어 추상 클래스를 사용해야 함
- 어떤 상태도없음
- 동작의 구현도없음
- 시그내처만 있음
- 이런 특징때문에 클래스하고는 약간 다른 규칙을 따름
public abstract class LoggerBase{
public abstract void log(String message);
}
public interface ILoggable{
void log(String message);
}
public final class ConsoleLogger extends LoggerBase{
...
}
public final class ConsoleLogger implements ILoggable{
}
- 메서드는 언제나 public
- 실질은 추상 클래스를 상속받는것과 전혀 다르지 않음
- java에서 사용하는 키워드만 다를 뿐
- extends와 implements키워드를 따로 분리하지 않는 언어도 많음
- C#과 C++은 두 경우에 모두 콜론을 사용
- 상속은 화살표 인터페이스는 점선 화살표
미구현으로 인한 컴파일 오류는 실수를 방지
- 인터페이스 안쓸때 흔히 저지르는 실수들
- 상속받은 메서드를 구현할 때 메서드 이름에 오타를 내는 경우
- 부모 클래스의 메서드 이름만 바꾸고 자식 클래스는 손 안대는 경우
- 자식 클래스에서 그 의도를 명백히 적어줄 수 있으면 됨
- 부모 클래스의 메서드를 오버라이딩
- 인터페이스의 메서드 시그내처를 구현
- C#,C++은 언어에서 지원하는 정식 키워드를 추가 : override
- 자바는 annotation 사용
public class Cat extends Animal{
@Override
public void shout(){
...
}
}
java 어노테이션
- 프로그램에 대한 메타데이터제공
- 프로그램의 일부가 아니어서 코드 실행에는 아무 영향을 안 미침
- 컴파일러에게 정보를 제공 @Deprecated
- 컴파일 또는 배포 중에 어노테이션을 기반으로 어떤 처리를 할 수 있음
- 실행중에 어노테이션을 기반으로 어떤 처리를 할 수 있음
interface 앞에 붙일 수 있는 접근 제어자
- public만 허용
- 생략도 가능
- 패키지 범위의 interface도 메서드는
인터페이스 앞에 I 붙일것
인터페이스 이름 뒤에 able이 붙기도 함
여러 인터페이스 구현하기
public interface ILoggable{
...
}
public interface ISavable{
...
}
public final class ConsoleLogger implements ILoggable, ISavable{
....
}
- java의 다중 인터페이스 상속 내부 구현???
- 각 인터페이스의 반환형만 다를시에 컴파일 오류 : 구현할 방법이 없음
인터페이스와 다중 상속
- 인터페이스는 다중 상속의 해결법 : 흉내낼수 있음
- 여전이 구현은 여러 번 해야함.
- 그러나 다형성은 사용가능
인터페이스를 이용한 시계 모델링
Clock : 상속
AnalogClock
DigitalClock
Interface:
IMountable
IWearable
AnalogWallClock : AnalogClock상속, IMountable
DigitalWallClokc : DigitalClock 상속, IMountable
AnlogWristWatch : AnalogClock상속, IWearable
DigitalWristWatch : DigitalClock 상속, IWearable
interface 용도 정리
- 함수포인터처럼 사용하는 인터페이스
- 다중상속 흉내 둘 다 다형성의 핵심
Object.clone()
protected Object clone() throws CloneNotSupportedException
- 복사를 원할경우 clone 메서드를 구현하면됨
- Clonable인터페이스를 상속 후 구현
- 그냥 Object의 clone을 오버라이딩하는 것이 아님
- exception이 있는 이유
- Clonable interface를 상속받지 않고 오버라이딩하면 이 예외 발생
public final class Robot implements Cloneable{
...
public Object clone() throws CloneNotSuppoertedException{
return super.clone();
}
}
- 각 클래스마다 clone의 의미는 다를 수 있음
- 얕은 복사
- Object를 반환하기에 캐스팅 필요
public final class Robot implements Cloneable{
...
public Object clone() throws CloneNotSuppoertedException{
Robot cloned = (Robot)super.clone();
cloned.head = (Head) head.clone();
return cloned;
}
}
- 얕은 복사 해결하려면 Head클레스에도 clone 메서드 구현