[자바의 정석] - 인터페이스(interface)

2023. 9. 26. 21:34·📝 끄적끄적/🖥️ 자바의 정석

인터페이스(interface)

인터페이스를 이해하려면 추상화, 다형성에 대한 이해가 필수적이다.

 

❓인터페이스란

⭐ 추상 메서드의 집합

 

핵심

구현된 것이 전혀 없는 설계도, 껍데기(모든 멤버가 public)

interface 인터페이스이름 {
		public static final 타입 상수이름 = 값;
		public abstract 메서드이름(매개변수목록);
}

인터페이스는 변수를 가질 수 없다. 무조건 상수만 가질 수 있다.

메서드는 전부 다 추상메서드 = 추상메서드의 집합

 

interface PlayingCared {
		public static final int SPACE = 4;
		final int DIAMOND = 3; //public static final int DIAMOND = 3;
		static int HEART = 2; //public static final int HEART = 2;
		int CLOVER = 1; //public static final int CLOVER = 1;

		public abstract String getCardNumber();
		String getCardKind(); // public abstract String getCardKind();
}

`public static final`

`public abstract`

이것이 default다. 없다면 생략된 것이다.

 

인터페이스의 상속

  • 인터페이스의 조상은 인터페이스만 가능(Object가 최고 조상이 아님)
  • 다중 상속이 가능하다. → 추상메서드는 충돌해도 문제가 없기 때문에

인터페이스의 구현

  • 인터페이스에 정의된 추상 메서드를 완성하는 것
  • 구현부는 인터페이스의 추상 메서드를 모두 구현해야 한다.
    • 일부만 구현하는 경우, 클래스 앞에 abstract를 붙여야 한다.
abstract class Fighter implements Fightable {
		public void move(int x, int y) { /* 생략 */ }
		public void attack() { /* 생략 */ }
}

 

❓추상 클래스와 인터페이스의 공통점

→ 추상 메서드를 가지고 있다.(미완성 설계도)

 

❓추상 클래스와 인터페이스의 차이점

→ 인터페이스는 변수(iv)를 가질 수 없다.

→ 생성자, 인스턴스메서드도 안됨

 

 

인터페이스를 이용한 다형성

  • 인터페이스도 구현 클래스의 부모인가? → 그렇게 칠 수 있다. 엄밀히 말하면 부모는 클래스만 가능하다.
  • 인터페이스 타입의 인스턴스 생성이 가능
interface Fightable{ /* 생략 */ }

abstract class Unit{ /* 생략 */ }

class Fighter extends Unit implements Fightable {
		public void move(int x, int y) { /* 생략 */ }
		public void attack() { /* 생략 */ }
}

`Unit u = new Fighter();`

`Fightable f = new Fighter();`

둘 다 가능하다.

대신 `Fighterble`에 정의된 메서드만 사용 가능하다.

 

  • 인터페이스 타입 매개변수는 인터페이스를 구현한 클래스의 객체만 가능
interface Fightable {
		void move(int x, int y);
		void attack(Fightable f); //**
}

`attack`메서드는 `Fightable`인터페이스를 구현한 클래스의 인스턴스만 들어올 수 있다!

 

  • 인터페이스를 메서드의 리턴타입으로 지정할 수 있다.
Fightable method() {
		Fighter f = new Fighter();
		return f; //Fighter는 Fightable의 구현클래스기 때문에 인터페이스로 반환가능
}

class Fighter extends Unit implements Fightable {
		public void move(int x, int y) { /* 생략 */ }
		public void attack() { /* 생략 */ }
}

 

❓인터페이스로 리턴하는 이유가 뭘까

→  다형성과 유연성을 활용하기 위해서

 

인터페이스를 반환하면 다음과 같은 장점이 있다.

- 다형성 활용: 인터페이스를 반환하면 여러 클래스의 인스턴스를 하나의 인터페이스 타입으로 다룰 수 있다.

이는 코드의 유연성을 높여준다.

예를 들어, `Fightable` 인터페이스를 구현하는 다른 클래스도 반환될 수 있으므로 코드를 확장하거나 변경할 때 유리하다.

- 코드 재사용: `Fightable `인터페이스를 구현하는 클래스가 여러 곳에서 사용될 경우,

인터페이스를 반환함으로써 해당 클래스의 인스턴스를 여러 곳에서 재사용할 수 있다.

즉 코드 중복을 피할 수 있다.

- 확장성: 나중에 코드를 확장할 때 새로운 클래스를 만들고 이 클래스가 `Fightable` 인터페이스를 구현하도록 하면,

이 새로운 클래스도 반환될 수 있으므로 코드 변경 없이 확장이 가능하다.

- 추상화: 인터페이스를 반환함으로써 구체적인 구현 세부사항을 숨길 수 있다.

이는 코드를 보다 추상적으로 만들어서 복잡성을 낮출 수 있다.

예를 들어 `Fightable` 인터페이스를 구현하는 다른 유닛들이 필요한 경우

해당 유닛 클래스를 작성하고, 그것을 `Fightable`로 반환하는 메서드에 적용하면 된다. 

이렇게 하면 코드의 확장성이 높고 유지 보수가 쉬워진다.

 

 

인터페이스의 장점

 

❓인터페이스란

  • 두 대상(객체) 간의 ‘연결, 대화, 소통’을 돕는 ‘중간 역할’을 한다.
    • 사람이 기계를 직접 조작하는 것보다는 껍데기를 통해 조작하는 게 더 편하다.
  • 선언(설계)과 구현을 분리시킬 수 있게 한다.
    • 변경에 유리하고 유연한 코드가 된다.
    • 구현부가 변경돼도 선언부는 안 바꿔도 된다.(느슨한 결합)

예시

아래와 같은 코드가 있을 때 `B`가 `C`라는 신규 클래스로 바꿔야 한다면

`A.methodA` 메서드를 변경해줘야 한다.

  • 의존관계 = A → B
class A {
		public void methodA(B b) {
				b.methodB();
		}
}

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`는 건드리지 않고,

`C`라는 클래스만 새로 추가해 `a.methodA(new C());` 이렇게 사용하면 된다.

  • 의존관계 = A → I → C
class A {
		public void methodA(I i) {
				i.methodB();
		}
}

interface I { void methodB(); }

class B implements I {
		public void methodB() {
				System.out.println("methodB()");
		}
}

class InterfaceTest {
		public static void main(String args[]){
				A a = new A();
				a.methodA(new B());
		}
}

장점

  • 개발 시간을 단축할 수 있다.

→ 구현부가 개발이 안되어있어도, 선언부가 구현이 되어있기 때문에 추상메서드지만 구현부가 완성된 것을 고려해 코드를 작성할 수 있다.

  • 변경에 유리한 유연한 설계가 가능하다.

→ 위의 코드에서 설명

  • 서로 관계없는 클래스들의 관계를 맺어줄 수 있다.

위의 상속 계층도에서 SCV, Tank, Dropship 클래스만 사용가능한 repair() 메서드를 만들고 싶은데, 아래와 같이 GroundUnit타입의 매개변수를 쓰자니 Marine클래스도 repair() 메서드를 사용하게 되어 원치 않은 결과를 얻게 된다.

void Repair(Tank t) {
	// Tank를 수리한다
}

void Repair(Dropship d) { // 오버로딩
	// Dropship을 수리한다
}

// 과도한 오버로딩을 방지하기위해 조상 클래스 타입 매개변수를 이용
void Repair(GroundUnit gu) {
	// 매개변수로 넘겨진 GroundUnit을 수리한다
}

아래처럼 Repairable 인터페이스를 구현했다는 공통점을 가지고 이들에 대해 관계를 맺어줄 수 있다.

interface Repairable {}

class SCV extends GroundUnit implements Repairable { }

class Tank extends GroundUnit implements Repairable { }

class Dropship extends AirUnit implements Repairable { }

// 실제 메서드 구현시
void Repariable(Repairable r) {
	if (r instanceof Unit) {
		Unit u = (Unit) r;
		while (u.hitPoint != u.Max_HP) {
			u.hitPoint++;
		}
	}
} // repair(Repairable r)

`Repariable`메서드에 대해 `Repairable`인터페이스를 구현한 객체만 들어올 수 있게 한다!

 

디폴트 메서드 static 메서드

  • 인터페이스에 디폴트 메서드, static메서드 추가 가능(JDK1.8부터)

인터페이스에는 새로운 메서드(추상 메서드)를 추가하기 어렵다는 특징이 있다.

A 인터페이스에 메서드를 추가하면 A의 구현 클래스들은 추가된 메서드를 구현해줘야 한다.

이 현상의 해결책으로 디폴트 메서드가 나왔다.

 

before

interface MyInterface {
	void method();
	void newMethod() {} // 디폴트 메서드는 몸통이 있음
}

after

interface MyInterface {
	void method();
	default void newMethod() {} // 디폴트 메서드는 몸통이 있음
}

이제 구현부가 인터페이스의 모든 추상 메서드를 구현하지 않아도 된다.

 

이걸로 괜찮을까?

디폴트 메서드는 인스턴스 메서드다. = 인터페이스 원칙 위반 (예외인 것)

또, 디폴트 메서드가 기존의 메서드와 충돌한다.

→ 구현 클래스에서 디폴트 메서드를 오버라이딩해야 한다.

충돌 생기면 그냥 오버라이딩 하자!

저작자표시 비영리

'📝 끄적끄적 > 🖥️ 자바의 정석' 카테고리의 다른 글

[자바의 정석] - 다형성  (0) 2023.09.25
[자바의 정석] - 추상 클래스와 추상메서드  (0) 2023.09.25
[자바의 정석] 참조변수의 형변환, instanceof 연산자  (0) 2023.09.24
[자바의 정석] 제어자, 캡슐화  (0) 2023.09.24
[자바의 정석] 상속, 참조변수 super, 생성자 super()  (0) 2023.09.23
[자바의 정석] 생성자, 변수/멤버 변수의 초기화  (0) 2023.09.22
'📝 끄적끄적/🖥️ 자바의 정석' 카테고리의 다른 글
  • [자바의 정석] - 다형성
  • [자바의 정석] - 추상 클래스와 추상메서드
  • [자바의 정석] 참조변수의 형변환, instanceof 연산자
  • [자바의 정석] 제어자, 캡슐화
현주먹
현주먹
끄적끄적 개발.log
  • 현주먹
    현주먹의 개발로그
    현주먹
  • 전체
    오늘
    어제
    • 전체글 (162)
      • 👶🏻 CS (15)
        • Operating System (8)
        • Database (4)
        • Data Structure (2)
        • Software Engineering (1)
      • 💻 Dev (54)
        • Java & OOP (24)
        • Spring (4)
        • JPA (5)
        • Test Code (1)
        • Database (1)
        • JSP & Servlet (13)
        • Etc (6)
      • 💡 Algorithm (25)
        • 인프런 (9)
        • 백준 (16)
      • 🛠 DevOps & Tool (11)
        • Linux (4)
        • AWS (1)
        • Git (2)
        • Etc (4)
      • 📝 끄적끄적 (57)
        • 후기 및 회고 (5)
        • TDD, 클린 코드 with Java 17기 (3)
        • F-Lab (23)
        • 🖥️ 자바의 정석 (11)
        • 📖 Clean Code (3)
        • 항해99 코테 스터디 (11)
  • 블로그 메뉴

    • 🐈‍⬛ GitHub
    • TIL
  • 인기 글

  • 태그

    JPA
    백준10250
    자바의정석
    에프랩
    객체지향
    PostGreSQL함수
    til
    데브클럽
    오라클
    로또 미션
    F-Lab
    TDD 클린 코드 with Java
    jsp
    NextSTEP
    개발자멘토링
    ==와 equals()
    코딩테스트준비
    f-lab 후기
    항해99
    코테스터디
    티스토리챌린지
    인프런 단어뒤집기
    오블완
    자바의신절판
    인프런 특정문자뒤집기
    99클럽
    백준
    에프랩 후기
    C
    개발자취업
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
현주먹
[자바의 정석] - 인터페이스(interface)
상단으로

티스토리툴바