반응형
인터페이스(Interface)
- 기능: 추상 메서드들의 집합. 인터페이스를 사용하기 위해서는 추상메서드의 집합인 인터페이스를 구현하는 클래스가 존재하여야 한다.
- 상속: 클래스와 달리 인터페이스는 다중상속을 허용 → 이유: 클래스는 복잡하지만 상대적으로 인터페이스는 단순한 추상메서드들의 집합
- 구현: 인터페이스들을 구현하는 클래스 입장에서는 인터페이스의 계층 구조를 따져서 그 인터페이스의 모든 부모 인터페이스에 존재하는 추상 메서드까지 클래스가 다 구현을 해주어야 한다. 하나의 인터페이스는 여러 인터페이스를 구현할 수 있다.
- 결론: 인터페이스를 구현하는 클래스는 자신이 구현하는 모든 인터페이스, 그리고 그 인터페이스의 부모 인터페이스까지 다 따져서 그 전체에 포함된 모든 추상 메서드를 다 오버라이딩해서 구현해주어야 한다.
- 구성: 인터페이스가 추상메서드와 상수를 가질 수 있다. (JDK 1.8 이후) default 메서드 + static 메서드도 가질 수 있다.
- 목적: 인터페이스는 인스턴스를 생성할 수 없고, 클래스 작성에 도움을 줄 목적으로 사용
- 용도: 정해진 규칙에 맞게 구현하도록 표준을 제시하는 데 사용
인터페이스의 작성
‘class’ 대신 ‘interface’를 사용한다는 것 외에는 클래스 작성과 동일
interface 인터페이스 이름 {
public static final 타입 상수이름 = 값;
public abstract 메서드이름(매개변수목록);
}
규칙
- 인터페이스는 static 필드가 존재하지 않는다. 선언과 동시에 초기화 하여야 한다.
- 인터페이스의 모든 멤버는 public이다.
- 모든 상수는 public static final이고 생략 가능
- 모든 메서드는 public abstract이고 생략 가능
인터페이스의 상속
- 인터페이스도 클래스처럼 상속이 가능(클래스와 달리 다중상속 허용)
- 인터페이스는 Object 클래스와 같은 최고 조상이 없다.
인터페이스의 구현
- 인터페이스를 구현하는 것은 클래스를 상속받는 것과 같다. 다만 ‘extends’ 대신 ‘implements’를 사용한다.
- 인터페이스를 구현하는 클래스는 자신이 구현하는 모든 인터페이스, 그리고 그 인터페이스의 부모 인터페이스까지 다 따져서 그 전체에 포함된 모든 추상 메서드를 다 오버라이딩해서 구현해주어야 한다.
- 상속과 구현이 동시에 가능하다. (extends와 implements를 함께 사용할 수 있다.)
인터페이스를 이용한 다형성
1. 인터페이스 타입의 변수로 인터페이스를 구현한 클래스의 인스턴스를 참조할 수 있다.
2. 인터페이스 타입의 레퍼런스 - 이미 완성된 타입의 프로그램을 외부에서 사용하기 위해서 부모 클래스 - 자식 클래스를 제어하기 위해서 → 각각의 상황에 맞게끔 사용할 것
3. 참조형 변수 레퍼런스를 만들 때 사용하는 타입의 종류
1)배열 2) 클래스 3) 인터페이스 4) enum
4. 인터페이스를 메서드의 매개변수 타입으로 지정 가능
void attack(Fightable f) {
// ...
}
5. 인터페이스를 메서드의 리턴타입으로 지정 가능
Fightable method() {
// ...
return new Fighter();
}
인터페이스의 장점
- (인터페이스가 제공이 된다면) 개발시간을 단축시킬 수 있다. 단, 인터페이스를 만드는 데 걸리는 시간도 생각해야 한다.
- 표준화가 가능하다.
- 서로 관계없는 클래스들에게 관계를 맺어 줄 수 있다.
- 독립적인 프로그래밍이 가능하다.
인터페이스의 장점 - 예제
비어있는 인터페이스 자주 사용
public interface Repairable {}
이유: 비어있는 인터페이스를 구현하는 클래스들은 수리가능한 유닛이 됨.
인터페이스의 이해
- 인터페이스는 두 대상(객체) 간의 ‘연결, 대화, 소통’을 돕는 ‘중간 역할’을 한다.
- 선언(설계)와 구현을 분리시키는 것을 가능하게 한다.
- 인터페이스를 이해하려면?
- 클래스를 사용하는 쪽(User)과 클래스를 제공하는 쪽(Provider)이 있다.
- 메서드는 사용(호출)하는 쪽(User)에서는 사용하려는 메서드(Provider)의 선언부만 알면 된다.
디폴트 메서드
구현부를 가지는 메서드.
인터페이스에 디폴트 메서드, static 메서드를 추가 가능
- 디폴트 메서드가 기존의 메서드와 충돌하는 경우 해결방법
- 여러 인터페이스의 디폴트 메서드 간의 충돌
- → 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩해야 한다.
- 디폴트 메서드와 조상 클래스의 메서드 간의 충돌
- → 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.
인터페이스 사용 예제
로또 번호 생성
package chap07;
public class MyLotto {
private int[] lotto;
public MyLotto() {
this.lotto = new int[6];
this.setLotto();
this.sortLotto();
}
// 로또 번호 중복 검사 메서드
boolean isUnique(int num) {
boolean result = true;
for (int i = 0 ; i < this.lotto.length ; i++) {
if (this.lotto[i] == num) {
result = false;
break;
}
}
// enhanced for문
// for (int lottoNum : this.lotto) {
// if (lottoNum == num) {
// result = false;
// break;
// }
// }
return result;
}
// 로또 배열 초기화 메서드
void setLotto() {
int temp;
for (int i = 0 ; i < this.lotto.length ; ) {
// 증감 연산자를 안넣는 이유 - 증감연산자를 넣으면 6번만 반복
// 중복이 발생하지 않는 로또 번호를 만들었을 때, 1을 증가시킴
while (true) {
temp = (int) (Math.random() * 45) + 1;
if (this.isUnique(temp)) {
lotto[i] = temp;
i++;
break;
}
}
}
}
// 선택 정렬
void sortLotto() {
int temp;
for (int i = 0 ; i < this.lotto.length - 1 ; i++) {
for (int j = i + 1 ; j < this.lotto.length ; j++) {
if (lotto[i] > lotto[j]) {
temp = lotto[i];
lotto[i] = lotto[j];
lotto[j] = temp;
}
}
}
}
int[] getLotto() {
return this.lotto;
}
public String toString() {
String result = "";
for (int num : lotto) {
result += num + " ";
}
return result;
}
}
실행 예제
package chap07;
public class Exam2_ans {
public static void main(String[] args) {
MyLotto lotto = new MyLotto();
System.out.print("\t [ 로또 추첨 프로그램 ]\n\t\t로또 추천 번호\n" +
"\t =================\n\t");
System.out.println(lotto);
}
}
반응형
'TIL' 카테고리의 다른 글
[TIL-6 / 230621] JPA 다양한 연관관계 매핑 (0) | 2023.06.21 |
---|---|
[TIL-5 / 230620] JPA 연관관계 매핑 기초, 연관관계의 주인 (0) | 2023.06.20 |
[TIL-3 / 230614] 다형성, JPA의 기본키 매핑 (0) | 2023.06.14 |
[TIL-2 / 230613] Java의 제어자, JPA 엔티티 매핑 (0) | 2023.06.13 |
[TIL-1 / 230612] JPA 영속성 컨텍스트 (0) | 2023.06.12 |