인터페이스
상속 관계가 없는 다른 클래스들이 서로 동일한 행위 즉, 메서드를 구현해야할 때 인터페이스는 구현 클래스들의 동일한 사용 방법과 행위를 보장
선언
public interface 인터페이스명 {
}
구성
- 모든 멤버 변수는 public static final ( 생략 가능 )
- 모든 메서드는 public abstract ( 생략 가능 ( static, default 메서드 예외 ) )
- 생략되는 제어자는 컴파일러가 자동으로 추가
public interface 인터페이스명 {
public static final char A = 'A';
static char B = 'B';
final char C = 'C';
char D = 'D';
void turnOn(); // public abstract void turnOn();
}
turnOn() 메서드 처럼 추상 클래스마냥 뒤에 볼륨 {} 없이 그냥 선언만 한다.
구현
public class 클래스명 implements 인터페이스명 {
// 추상 메서드 오버라이딩
@Override
public 리턴타입 메서드이름(매개변수, ...) {
// 실행문
}
}
- implements 키워드를 이용해서 구현
- 인터페이스의 추상 메서드는 반드시 오버라이딩 되어야함.
- 만약 인터페이스의 추상 메서드를 일부만 구현해야 한다면 해당 클래스를 추상 클래스로 변경시켜준 후에 상속시켜서 다음에 남은 메서드를 구현하는 방법으로 넘길 수 있음
상속
- 마찬가지로 extends 키워드를 사용해 상속시킴
- 인터페이스는 클래스와는 다르게 다중 상속이 가능
public class Main extends D implements C {
@Override
public void a() {
System.out.println("A");
}
@Override
public void b() {
System.out.println("B");
}
@Override
void d() {
super.d();
}
public static void main(String[] args) {
Main main = new Main();
main.a();
main.b();
main.d();
}
}
interface A {
void a();
}
interface B {
void b();
}
interface C extends A, B {
}
class D {
void d() {
System.out.println("D");
}
}
Main 클래스는 D 로부터 상속받음.
D 를 보면 d 메서드가 있고 이는 "D" 를 출력함.
하지만 자식 클래스인 Main 에서 메서드 d 는 super.d(); 로 재선언 되어있지만 결국 이는 동일한 결과 출력
그리고 인터페이스 C 를 받음
인터페이스 C 는 A,B 로 부터 상속받음
인터페이스 A 는 인터페이스 메서드 a, 인터페이스 B 는 메서드 b 를 가지고 있음
메서드 a 와 b 는 각 각 "A", "B" 를 출력하는 걸로 Override 되어있음
결국 Main 함수의 생성자에서 인스턴스화 시킨다음 a,b,d 를 호출하면 A, B, D 를 출력한다.
default 메서드
추상 메서드의 기본적인 구현을 제공하는 메서드
- 메서드 앞에 default 키워드를 붙이며 블럭{ }이 존재해야 함.
- default 메서드 역시 접근 제어자가 public이며 생략이 가능.
- 추상 메서드가 아니기 때문에 인터페이스의 구현체들에서 필수로 재정의 할 필요는 없음.
public class Main implements A {
@Override
public void a() {
System.out.println("A");
}
public static void main(String[] args) {
Main main = new Main();
main.a();
// 디폴트 메서드 재정의 없이 바로 사용가능합니다.
main.aa();
}
}
interface A {
void a();
default void aa() {
System.out.println("AA");
}
}
인터페이스 A 에서 aa 메서드 앞에 default 를 붙였고 그랬기 때문에 main 메서드에서 main.aa() 로 오버라이딩 없이 사용 가능
static 메서드
static 의 특성 그대로 인터페이스의 sattic 메서드 또한 객체 없이 호출이 가능
public class Main implements A {
@Override
public void a() {
System.out.println("A");
}
public static void main(String[] args) {
Main main = new Main();
main.a();
main.aa();
System.out.println();
// static 메서드 aaa() 호출
A.aaa();
}
}
interface A {
void a();
default void aa() {
System.out.println("AA");
}
static void aaa() {
System.out.println("static method");
}
}
인터페이스 A 에서 static 으로 선언된 aaa 메서드가 main 메서드에서 A.aaa 로 객체 선언 없이 바로 사용이 가능
다형성
타입 변환
public class Main {
public static void main(String[] args) {
// A 인터페이스에 구현체 B 대입
A a1 = new B();
a1.a();
// a1.b(); // 불가능
System.out.println("\nB 강제 타입변환");
B b = (B) a1;
b.a();
b.b(); // 강제 타입변환으로 사용 가능
System.out.println();
// A 인터페이스에 구편체 B를 상속받은 C 대입
A a2 = new C();
a2.a();
//a2.b(); // 불가능
//a2.c(); // 불가능
System.out.println("\nC 강제 타입변환");
C c = (C) a2;
c.a();
c.b(); // 강제 타입변환으로 사용 가능
c.c(); // 강제 타입변환으로 사용 가능
}
}
interface A {
void a();
}
class B implements A {
@Override
public void a() {
System.out.println("B.a()");
}
public void b() {
System.out.println("B.b()");
}
}
class C extends B {
public void c() {
System.out.println("C.c()");
}
}
C 는 B 를 자식 클래스이고 B 는 인터페이스 A 를 갖고있다.
그럼 C > B > A 순서
A a2 = new C() ; 로 자동 형 변환을 했기 때문에
a2 에서는 C 에 들어가 있는 메서드 c, B 에 들어가있는 메서드 b 는 사용할 수 없다.
사용하기 위해서 C c = (C) a2 ;
로 강제 형 변환을 한 것을 알 수 있다.
'컴퓨터 프로그래밍 > Java' 카테고리의 다른 글
[Java] Generic (0) | 2024.08.04 |
---|---|
[Java] 예외처리 (0) | 2024.07.30 |
[Java] 상속 (0) | 2024.07.29 |
[Java] this와 this(), 접근 제어자, package와 import (0) | 2024.07.29 |
[Java] 생성자 (0) | 2024.07.28 |