인터페이스란?
추상메서드 집합(추상메서드만!!)
추상메서드, 상수, static메서드, 디폴트메서드 외에 허용 X
interface 인터페이스이름 {
(public static final) Type 상수이름 = 값;
(public abstract) 메서드 이름 (매개변수목록); // 추상메서드
}
- 모든 멤버변수는 public static final 이고, 생략 가능
- 모든 메서드는 public abstract 이고, 생략 가능(단, static메서드와 디폴트 메서드는 예외)
- public은 항상 예외가 없어서 생략 가능
인터페이스 | 추상클래스 |
추상메서드 집합 (iv 가질 수 없다.) |
일반클래스에 추상메서드를 가지고 있음 일부가 추상메서드이다. (생성자, iv, 인터페이스 메서드,,,) |
기본 설계도(구현된 것이 없는 설계도 껍데기) | 미완성 설계도 |
implements 상속 | extends 상속 |
모든 멤버가 public | |
✔ 공통점) 추상메서드를 가지고 있다(미완성 설계도) | |
✔ 차이점) 인터페이스는 Iv를 가질 수 없다. |
인터페이스의 상속
인터페이스는 인터페이스로부터만 상속받을 수 있다.(Object가 최고 조상이 아니다.)
클래스와 달리 다중상속 가능(여러 인터페이스로부터 상속받는 것 가능)
→ 왜? 추상메서드는 {몸통(구현체)}가 없기 때문에 메서드가 충돌해도 문제가 없기 때문이다.
(클래스는 출동 문제가 있기 때문에 단일 상속)
interface Fightable extends Movable, Attackable {} // 다중상속 가능
인터페이스의 구현
인터페이스도 추상클래스처럼 그 자체로는 인스턴스를 생성할 수 없고,
추상클래스가 상속을 통해 추상메서드를 완성하는 것처럼, 인터페이스도 상속을 통해 {몸통(구현체)}를 만들어주는 클래스를 작성해야 한다.
interface 인터페이스이름 {
void move(int x, int y); // public abstract 생략 가능
void attack(Unit u); // public abstract 생략 가능
}
- 인터페이스를 완전한 클래스 만들기
class 클래스이름 implements 인터페이스이름 {
public void move (int x, int y) {// 내용생략};
public void attack (Unit u) {// 내용생략};
}
- 인터페이스 구현을 일부만 한다면
상속 받은 메서드 중 하나라도 구현하지 않는다면, 자손클래스에서 추상클래스(abstract)로 지정해줘야 한다.
// 생략되어 있는 메서드에 abstract가 있기 때문에 클래스 앞에도 abstract는 붙여야 함
abstract class 클래스이름 implements 인터페이스이름 {
public void move (int x, int y) { //내용생략 }; // 1개만 구현
// public abstract void attack (Unit u) { //내용생략}; // 이게 생략되어 있음.
}
- 상속과 구현을 동시에 할 수 있다.
class 클래스이름 extends Unit implements 인터페이스이름{
public void move(int x, int y) { // 내용생략 };
public void attack(Unit u) { // 내용생략 };
}
📌 주의! 오버라이딩할 때는 조상의 메서드보다 넓은 범위의 접근 제어자를 지정해야한다.
인터페이스 메서드에 public abstract가 기본 양식이다.(생략가능하기 때문에 주의하자)
그러므로 오버라이딩해서 구현할 때(implements) 접근제어자는 public을 사용해야한다.(public보다 큰 접근제어자는 없다.)
인터페이스를 이용한 다형성
- 인터페이스는 메서드의 매개변수의 타입으로 사용될 수 있다.
void attack (Fightable f) { ... };
인터페이스 타입의 매개변수가 갖는 의미는 ⭐메서드 호출 시 해당 인터페이스를 구현한 클래스의 인스턴스를 매개변수로 제공해야 한다는 것이다.
attack 메서드를 호출할 때는 매개변수로 Fightable인터페이스를 구현한 클래스의 인스턴스를 넘겨주어야 한다.
class Fighter extends Unit implements Fightable {
public void move (int x, int y) {...};
public void attack (Fightable f) {...}; // 매개변수로 Fightable인터페이스를 구현한 클래스의 인스턴스를 넘겨주어야 한다.
}
Fightable인터페이스를 구현한 Fighter 클래스가 있을 때, attack메서드의 매개변수로 Fighter인스턴스를 넘겨 줄 수 있다.
즉, attck(new Fighter())를 넣을 수 있다.
- 또한, 메서드의 리턴타입으로 인터페이스의 타입을 지정하는 것 역시 가능한다.
Fightable method() {
...
Fighter f = new Fighter();
return f;
// f 앞에는 (Fightable) 형변환이 생략되어 있다. 자손이 조상으로 형변환 되는 것은 생략가능하다.
// 위의 두 개를 한 문장으로 바꾸면 return new Fighter();
}
Fightable : 인터페이스
Fighter : 인터페이스 구현
⭐리턴타입이 인터페이스라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미한다.
인터페이스의 장점
- 두 대상(객체) 간의 '연결, 대화, 소통'을 돕는 '중간 역할'을 한다.
- 선언(설계)와 구현을 분리시킬 수 있게 한다.
- 변경에 유리한 유연 설계 가능(느슨한 결합)
- 개발 시간 단축
- (구현체가 완성되지 않아도 인터페이스를 호출해서 우선 코드 작성하면 됨)
- 변경에 유리한 유연한 설계 가능
- 표준화 가능(ex. JDBC)
8. 서로 관계없는 클래스들을 관계를 맺어 줄 수 있다.
인터페이스의 이해
클래스를 사용하는 쪽(User)과 클래스를 제공하는 쪽(Provider)가 있다.
메서드를 사용(호출)하는 쪽 (User) 에서는 사용하려는 메서드(Provider)의 선언부만 알면 된다.(내용은 몰라도 된다.)
- 인터페이스 적용 X 예시
class A {
public void method(B b) {
}
}
class B {
public void method () {
System.out.println("methodB()");
}
}
class InterfaceTest {
public static void main(String args[]) {
A a = new A();
a.method(new B());
}
}
- 인터페이스 적용
class A {
void autoPlay(I i) {
i.play;
}
}
interface I {
public abstract void play();
}
class B implements I {
public void play() {
System.out.println("B Class");
}
}
class C implements I {
public void play() {
System.out.println("C Class");
}
}
class InterfaceTest2 {
public static void main(String[] args) {
A a = new A();
a.autoPlay(new B()); // void autoPlay(I i)호출
a.autoPlay(new C()); // void autoPlay(I i)호출
}
}
클래스 A는 인터페이스 I만 호출하고, 클래스 B와는 직접적인 연관이 없어진다.
클래스 A는 클래스B의 변경에 영향을 받지 않는다.
클래스 B가 클래스 C로 변경되어도 인터페이스만 영향을 받는다.(느슨한 결합으로 변화에 유연한 설계가 가능해진다.)
디폴트 메서드와 static 메서드
인터페이스에 새로운(추상 메서드)를 추가하기 어려움 → 해결 : 디폴트 메서드
디폴트 메서드는 인스턴스 메서드(인터페이스 원칙 위반-예외)
디폴트 메서드는 앞에 default를 붙이며, 추상메서드와 달리 일반 메서드처럼 몸통{}이 있어야 한다.
디폴트 메서드는 접근 제어자가 public이며, 생략 가능하다.
- 디폴트 메서드가 기존의 메서드와 충돌할 때의 해결책 → 그냥 직접 오버라이딩하면 해결
1. 여러 인터페이스의 디폴트 메서드 간의 충돌
인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩해야 한다.
2. 디폴트 메서드와 조상클래스의 메서드 간의 충돌
조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.
'공부 > Java' 카테고리의 다른 글
[Java] 예외처리 (0) | 2024.03.29 |
---|---|
[Java] implement vs. extends (2) | 2024.03.28 |
메서드 (0) | 2023.05.24 |
메서드 등 (0) | 2023.03.31 |
문자 '2'에 -'0'을 했을 때 숫자2로 변환되는 이유 (0) | 2023.03.31 |