[작성일: 2023. 01. 30]
목차
인터페이스(Interface)
- 추상 메서드의 집합(프로그래밍 관점)
- 구현된 것이 전혀 없는 설계도 껍데기(모든 멤버가 public) ➡️객체를 만들 수 없음.
- 하나의 시스템을 구성하는 두 개의 요소, 또는 두 개의 다른 시스템이 상호 작용을 할 수 있게 하는 접속 경계
- 접속하기 위한 하드웨어, 소프트웨어, 조건, 규약 등을 포괄적으로 가리킴.
interface 인터페이스명 { // iv, cv 등 변수는 가질 수 없음. public static final 타입 상수이름 = 값; // 상수 public abstract 메서드명(매개변수 목록); // 추상 메서드({}이 없음.) } // 모든 인터페이스의 멤버는 public만을 가짐. interface PlayingCard { public static final int SAPDE = 4; final int DIAMOND = 3; static int HEART = 2; int CLOVER = 1; // public static final 일부or전부 생략 가능 public abstract String getCardNumber(); /* public abstract 생략 가능 */ String getCardKind(); }
Java의 인터페이스
- 프로그램과 프로그램을 연결해 주는 것
- [규제]
- 특정한 규약에 의해 개발하도록 하는 목적
- 클래스가 인터페이스를 사용하려면 반드시 인터페이스가 만들라고 한 메서드들을 전부 구현해야 함.
- 인터페이스의 메서드를 구현하지 않으면 컴파일이 되지 않음.
인터페이스를 왜 만들었을까?
ex)
계산기 기능 개발을 하던 도중,
계산기 자체는 A가 개발하고 계산기를 이용하는 어플은 B가 개발을 했다.
동시에 개발을 하다 보니 B는 A가 잘 개발할 것을 가정하고 어플 개발을 진행한다.
➡️ 나중에 보니 A는 add(a, b) 메서드이고, B는 add(int a[]) 메서드로 개발하였다.
인터페이스 사용법
[public] // [규제]이기 때문에 무조건 public [public] interface 인터페이스명 {} // 클래스 자리에 interface 넣기 [public][static][final] 자료형 상수명 = 값; [public] 리턴타입 메서드명(인자); [public] default 리턴타입 메서드명(인자) {} [public] static 리턴타입 메서드명(인자) {} class 클래스명 implements 인터페이스명 {} // 클래스 생성 시 가장 복잡한 형태 class 클래스명 extends 부모클래스 implements 인터페이스1, 인터페이스2 ... throws Exception // 간단 예제 interpace Interface1 { public void myMethod1(); } class Class1 implements Interface1 { public void myMethod1() { 내가 구현; (내용이 없어도 존재해야 함) } }
인터페이스의 상속
- 인터페이스의 조상은 인터페이스만 가능(Object가 최고 조상이 아님.)
- 다중 상속(조상이 여러 개) 가능 (추상 메서드는 충돌해도 문제없음.➡️구현부가 없기 때문.)
- 부모 클래스의 기능을 자식 클래스가 물려받는 것.
interface Fightable extends Movale, Attackabe { } // 다중 상속 interface Movable { // 인터페이스의 조상은 인터페이스만 가능 /* 지정된 위치(x, y)로 이동하는 기능의 메서드*/ void move(int x, int y); } interface Attackable { /* 지정된 대상(u)을 공격하는 기능의 메서드*/ void attack(Unit u); } // 인터페이스끼리 상속 interface I3 { void x(); } interface I4 extends I3 { void y(); } class C2 implements I4 { void x() { } void y() { } }
인터페이스의 구현
- 인터페이스에 정의된 추상 메서드를 완성(구현)하는 것
- 인터페이스의 구현과 상속은 완전히 다름.
- 인터페이스 구현은 자식 클래스가 반드시 만들도록 강제하는 것.
- 클래스 선언은 class, 인터페이스 선언은 interface
- 클래스 상속은 extends, 인터페이스 구현은 implements
- 하나의 클래스가 여러 개의 인터페이스도 구현 가능함.
class 클래스 이름 implements 인터페이스 이름 { // 인터페이스에 정의된 추상메서드를 모두 구현해야 함. } class Fighter implements Fightable { // 모든 추상 메서드가몸통이 생겼기 때문에 abstract 없음. // Fighter클래스는 Fightable 인터페이스를 구현했다고 표현함. public void move(int x, int y) { /*내용 생략*/ } public void attack { /*내용 생략*/ } } // 일부만 구현하는 경우 클래스 앞에 abstract를 붙여야 함. abstract class Fighter implements Fightable { public void move(int x, int y) { /*내용 생략*/ } } //하나의 클래스가 여러 개의 인터페이스 구현 가능 interface I1 { void x(); } interface I2 { void y(); } class C1 implements I1, I2{ void x() { } void y() { } }
Q&A
Q. 인터페이스란?
A. 추상 메서드의 집합
abstract clss Player { abstract void play(int pos); abstract void stop(); }
Q. 인터페이스의 구현이란?
A. 인터페이스의 추상메서드 몸통{} 만들기(미완성 설계도 완성하기)
class AudioPlayer extends Player { // 추상클래스 구현 void play(int pos) { /* 내용 생략 */ } void stop() { /* 내용 생략 */ } } class Fighter implements Fightable { // 인터페이스 구현 구분 잘 하기 public void move(int x, int y) { /* 내용 생략 */ } public void attack(Unit u) { /* 내용 생략 */ } }
Q. 추상 클래스와 인터페이스의 공통점은?
A. 추상 메서드를 가지고 있음.(미완성 설계도)
Q. 추상 클래스와 인터페이스의 차이점은?
A. 인터페이스는 iv, 생성자, im을 가질 수 없음. (상수, static메서드, default메서드, 추상메서드만 가질 수 있음.)
인터페이스를 이용한 다형성
- 인터페이스도 구현 클래스의 부모로 생각할 수 있음.
- 인터페이스 타입 매개변수는 인터페이스를 구현한 클래스의 객체만 가능함.
- 인터페이스를 메서드의 리턴타입으로 지정할 수 있음.(Fightable 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 뜻)
Unit u = new Fighter(); // 가능. 조상클래스 Fightable f = new Fighter(); // 가능. 인터페이스 // 자손객체 -> 조상클래스 가리키는 것 가능 interface Fightable { void move(int x, int y); void attack (Fightable f); // attack의 매개변수 타입이 인터페이스임. // 매개변수의 타입이 인터페이스인 경우는 인터페이스를 구현한 클래스의 객체만 받겠다는 뜻. } f.move(100, 200); f.attackr(new Fighter()); // Fighter의 객체가 아무리 많아도 인터페이스에 선언된 멤버 2개만 사용할 수 있음. //인터페이스를 리턴타입으로 지정 가능 Fightable method() { ... Fighter f = new Fighter(); return f; // 인터페이스를 구현한 객체 반환 // return new Fighter(); 와 같은 문장임. }
abstract class Unit2 { int x, y; abstract void move(int x, int y); void stop() { System.out.println("멈춥니다."); } } interface Fightable { // 인터페이스의 모든 메서드는 public abstract가 붙음. void move(int x, int y); // public abstract 생략됨 void attack(Fightable f); // public abstract 생략됨 } class Fighter extends Unit2 implements Fightable { // 오버라이딩 규칙: 조상보다 접근제어자 범위가 좁으면 안 됨. public void move(int x, int y); { System.out.println(x + "," + y + "로 이동"); } public void attack(Fightable f); { System.out.println(f + "를 공격"); } } Fightable getFightable() { // 메서드 추가 Fighter f = new Fighter(); return (Fightable)f; public class FighterTest { public static void main(String[] args) { Fighter f = new Fighter(); Fightable f2 = f.getFightable(); // 반환타입하고 일치해야 함. } }
인터페이스의 장점
- 두 대상(객체) 간의 '연결, 대화, 소통'을 돕는 '중간 역할'을 함.
- 선언(설계)과 구현을 분리시킬 수 있게 함. ➡️ 개발 시간 단축, 변경에 유리하고 유연한 설계 가능
- 표준화가 가능함.(JDBC➡️인터페이스의 집합)
- 서로 관계없는 클래스들을 관계 맺어줄 수 있음.
// 선언과 구현을 분리시킬 수 있음. class B { public void method() { System.out.println("methodInB"); } //껍데기+알맹이 -> 유연하지 못 하고 변경에 불리함. } // ⬇️ 새로운 interface 선언, 껍데기 Interface I { public void method(); // class B의 선언부만 떼어내기 } // ⬇️ // 구현, 알맹이 class B implements I { public void method() { System.out.println("methodInB"); } }
//2. 인터페이스 덕분에 B가 변경되어도 다른 클래스(A)는 안 바꿀 수 있음. //느슨한 결합 ↔️ 강한결합 //직접적인 관계의 두 클래스 // (A-B)// A(User) ➡️ B(Provider) class A { public void methodA(B b) { b.methodB(); // B클래스의 메서드 호출 } } class B { public void methodB() { System.out.println("methodB()"); } } class InterfaceTest { public static void main(String[] args) { A a = new A(); a.methodA(new B()); } } // 위의 코딩보다는 B클래스를 인터페이스로 분리하는 것이 유연한 코딩임. // A(User) ➡️ I class A { pullic void methodB(I i ) { // I를 사용하도록 바꿈 i.methodB(); } } interface I { // 껍데기, 추상메서드 void methodB(); } class B implements I { //알맹이, 인터페이스 구현 public void methodB() { System.out.println("methodB()"); } } class C implements I { // B를 C로만 변경해주면 되고 A를 건들 필요 없음 public void methodB() { System.out.println("methodB() int C"); } }
// 서로 관계없는 클래스들을 관계맺어 줄 수 있음 Interface Repairablee {} class SCV extends GroundUnit implements Repairable { // ... } class Tank extends GroundUnit implements Repairable { // ... } class Dropship extends GroundUnit implements Repairable { // ... } // Repairable 구현 void repair(Repairable r) { if (r instanceof Unit) { Unit u = (Unit)r; while(u.hitPoint!=u.MAX_HP) { u.hitPoint++; // Unit의 HP를 증가시킴. } }

🐣 해당 게시글은 자바의 정석(남궁성 님) 영상으로 함께 공부하며 요약/정리한 글입니다.
🐣 입문 개발자가 작성한 글이므로 틀린 내용이나 오타가 있을 수 있습니다.