- 두 객체를 연결하는 역할
- 다형성 구현에 중요함
- 다형성 : 인터페이스 하나의 이름으로 여러 형태의 객체를 사용할 수 있음
추상 메서드
- 메서드 내용을 구현하지 않고 선언만 한 메서드
{}중괄호 없는 리턴타입, 메소드명, 매개변수만 선언public abstract생략해도 컴파일 과정에서 자동으로 붙음- 추상 메서드를 하나라도 가진 클래스, 인터페이스는 객체 생성 불가능
- 인터페이스를 implements한 클래스에서 추상 메소드 오버라이딩(재정의) 해야함!(필수)
인터페이스 선언
새로운 interface 파일 생성
public interface 인터페이스명{ // 필드, 메소드 등 }
- 접근 제한자 :
default(같은 패키지 내),publicnew를 이용한 객체 생성 불가
- 불완전한 메서드를 포함하고 있기 때문
- 변수 타입으로는 쓸 수 있음
인터페이스 변수명 = null;구현 클래스 선언
public class 클래스명 implements 인터페이스명{}
- 인터페이스에 정의된 추상 메소드에 대한 실행 내용
implements키워드를 이용해서 해당 클래스가 인터페이스 사용할 수 있다고 선언- 인터페이스는 추상 메서드가 있어서 해당 클래스에서 재정의(
@Override) 필수!!변수 선언
인터페이스명 변수명 = new 클래스명();
- 인터페이스는 참조 타입으로 구현 객체(클래스)를 대입해야함
- 클래스 객체를 대입하면 자동형 변환이 됨
상수 필드
(public static final) 타입 상수명 = 값;
- 인터페이스에 선언된 필드는
public static final특성을 갖음 (불변의 상수 필드)
public static final는 생략 가능- 구현된 클래스에서 불변 변수로 공유하기 좋음
- 이름 규칙 : 대문자, 다른 단어일때
_로 연결- ex)
int MAX_COUNT = 100;
public class 구현클래스명 implements 인터페이스1, 인터페이스2 { // 모든 추상 메소드 재정의 }
-> 인터페이스1 변수 = new 구현클래스명(); (O)
-> 인터페이스2 변수 = new 구현클래스명(); (O)
public interface 자식인터페이스 extends 부모인터페이스1, 부모인터페이스2{...}
-> 자식인터페이스 변수 = new 구현클래스명(); (O)
-> 부모인터페이스1 변수 = new 구현클래스명(); (O)
-> 부모인터페이스2 변수 = new 구현클래스명(); (O)

구현클래스 변수 = (구현클래스) 인터페이스변수;
인터페이스명 변수명 = new 클래스명(); (자동 타입 변환)일때는 인터페이스에 선언된 메소드만 사용 가능구현클래스 변수 = (구현클래스) 인터페이스변수; (강제 타입 변환)일때는 클래스(객체)에 선언된 메소드도 사용 가능!

메소드 재정의 + 자동 타입 변환 => 다형성

if(object instanceof InterfaceType){}
object(객체)가 InterfaceType(인터페이스)을 구현하고 있는가?instanceof 연산 결과가 true이면 우측 타입 변수 사용할 수 있어서 강제 타입 변환 필요 없음Vehicle vehicle = new Bus(); // 인터페이스 타입으로 선언했지만 실제 객체는 Bus
if (vehicle instanceof Bus bus) {
//bus 변수 사용 가능
bus.announce(); // 형변환 없이 Bus 메서드 사용 가능
}
public abstract class 클래스명
abstract 키워드 붙여줘야함


- 코드를 유연하게 만들기 위해 (다형성 활용)
Vehicle vehicle = new Bus(); // 자동 타입 변환 Vehicle vehicle = new Taxi(); // 이렇게도 가능
vehicle.run();처럼 동일한 코드로 다양한 객체(Bus, Taxi 등)를 처리할 수 있음- 코드를 유연하고 재사용성 높게 설계 가능!
-> 실제 객체는 다양하지만, 같은 인터페이스 타입으로 제어할 수 있음!
- 인터페이스 기반 프로그래밍은 설계가 깔끔해짐
void startRide(Vehicle v) { v.run(); // Bus든, Taxi든 동작 가능 }
Vehicle인터페이스만 알고 있어도 다양한 구현체(Bus, Taxi 등)를 받을 수 있음.- 확장성과 유지보수성이 엄청 좋아짐
-> 개발자들은 이런 "약한 결합(loose coupling)" 구조를 선호함
- 구현체에 의존하지 않도록 하기 위해
ArrayList,LinkedList등도List인터페이스를 구현하고 있음
→List list = new ArrayList();처럼 쓰는 거야.void processList(List<String> list) { // 내부가 ArrayList든 LinkedList든 상관없음 }
- 이 방식은 구현 클래스 변경이 자유로워서 유지보수가 편함!!
하지만, 구현 클래스의 메서드는 못 쓰는 이유??
"인터페이스나 부모 클래스에 선언된 기능만 사용할 거면, 그 타입만 알면 된다"라고 생각하기 때문
강제 타입 변환은 언제 사용??
Bus만의 고유 기능(checkFare())을 꼭 써야 하는 상황일 때만 캐스팅해서 사용if (vehicle instanceof Bus) {
Bus bus = (Bus) vehicle;
bus.checkFare(); // Bus만의 기능
}