저번에 추상메소드를 배웠고, 오늘은 그것과 비슷한 인터페이스를 배워보려 합니다.
<인터페이스(interface : 틀)>
추상 클래스를 고도화 시킨 문법. 상수와 추상메소드만 존재합니다.
변수가 존재하지 못하는이유 -> 틀은 변할수 없기때문에 변하는 변수는 들어갈수 없습니다.
구현은 인터페이스를 지정한 클래스에서 진행하고, 인터페이스를 다른클래스에 지정할 때에는 implements 키워드를 사용한다.
★Point! 인터페이스도 타입이다!
★Point! 인터페이스는 클래스가 아니다!!
★Point! 상수만 작성이 되기때문에 상수라고 표시 안하고 int 만써도 상수로 인식이 된다.
★Point! 인터페이스는 틀이고 공유의 목적이기때문에 static이 붙어야 한다.
<추상클래스와 인터페이스 간의 관계>
인터페이스를 클래스에 바로 지정하면 모든 메소드에 강제성이 부여되어서 전부 다 구현 해야합니다.
하지만 일반적인 상황에서는 모든 것이 아닌, 필요한 메소드를 골라서 재정의 해야한다.
인터페이스를 직접 지정하지 않고 다른 클래스에 지정한 후 바디를 만들어 놓는다면,
강제성이 소멸되고 이 클래스를 상속받아서 필드를 구현한다면, 골라서 재정의 할 수 있게 됩니다.
이때 중간에서 강제성을 없애주려는 클래스를 추상클래스로 선언하며, 클래스 이름 뒤에
Adapter를 붙여서 목적을 알려줍니다.
( 예 : interface 이름 : Electronics, Electronics의 강제성을 없애주기 위한 추상클래스 이름 : ElectronicsAdapter )
★Point! 추상클래스는 인터페이스의 강제성이 너무 강하기때문에 강제성을 해제해줄때 주로 사용한다.!!!!!
// 인터페이스
public interface Pet {
final static int eyes = 2;
int nose = 1;
abstract void getHand();
void shakeTail();
void charms();
void bark();
}
/// PetAdapter
public abstract class PetAdapter implements Pet {
@Override
public void getHand() {;}
@Override
public void shakeTail() {;}
@Override
public void charms() {;}
@Override
public void bark() {;}
}
// Puppy와 같이 인터페이스의 모든 메소드를 구현해도 됩니다.
public class Puppy implements Pet {
@Override
public void getHand() {
// TODO Auto-generated method stub
System.out.println("손! 살포시 들어서 내려놓기 착!");
}
@Override
public void shakeTail() {
// TODO Auto-generated method stub
System.out.println("좌우로 흔든다");
}
@Override
public void charms() {
// TODO Auto-generated method stub
System.out.println("불쌍한 척 쳐다보고 배를 보여준다.");
}
@Override
public void bark() {
// TODO Auto-generated method stub
System.out.println("멍멍! 왈왈!");
}
}
// 호랑이와 같이 Pet의 기능중에 선택적으로 기능을 구현하려면 인터페이스를 추상클래스에서 미리 다 구현하고
// 필요기능만 다시 Tiger 클래스에서 재정의를 해줄수도 있습니다.
public class Tiger extends PetAdapter{
@Override
public void shakeTail() {
// TODO Auto-generated method stub
System.out.println("먹잇감으로 선택된다.");
}
@Override
public void bark() {
// TODO Auto-generated method stub
System.out.println("어흥");
}
}
<마커 인터페이스>
똑같은 인터페이스이지만 목적이 다른 인터페이스
marker = 표시 -> 즉 표시하기 위한 인터페이스
클래스들을 그룹화 하기 위한 목적으로 사용합니다.
인터페이스는 지정한 클래스의 부모이며, 모든 자식은 부모의 타입이므로 마커 인터페이스를 지정받은 클래스들이 하나의 타입으로 묶이게 된다.
클래스 | 삼X | LX | 롯X | 두X |
지정된 인터페이스 | 자동차 | 전자 | 타워 | 야구 |
야구 | 야구 | 월드 | 중공업 | |
보험 | 헬로비전 | 야구 | 동아 |
이렇게 마커인터페이스를 야구로 만들면 각 클래스가 내용이 달라도 부모타입인 야구인 하나의 타입으로 묶이게 됩니다.
<다중 상속>
하나의 자식에 여러부모를 상속받는것!, 그러나 상속은 하나만 받을 수 있습니다.
여러 부모 클래스를 상속하는 것을 다중 상속이라고 합니다. JAVA는 모호성 때문에 다중 상속을 지원하지 않습니다.
하지만 JDK 8버전 부터는 인터페이스에 default 메소드 선언을 허용하며, 여러 개를 지정할 수 있는 인터페이스 특성상 다중 상속을 지원하는 것이나 다름이 없다.
-> 그러나 기본적으로 다중상속을 하지 않는다고 봅니다.
<모호성>
하나의 자식이 여러 부모를 상속받을 때 부모 필드에 동일한 이름의 필드가 있다면, 어떤 부모의 필드인지 알 수가 없다.
- 모호성 해결 방안
상황 1 : 두 개의 인터페이스 내에 같은 이름과 매개변수의 메소드가 선언되어 있다.
-> 해결 : 자식 클래스에서 재정의 하여 사용한다. (interface.super.메소드명)
상황 2 : 부모 클래스의 메소드와 인터페이스의 디폴트 메소드의 이름과 매개변수가 같다.
-> 부모 클래스의 메소드가 사용된다.