일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- regression
- 티스토리챌린지
- 지도학습
- gpt
- deep learning
- Classification
- OpenAI
- Machine Learning
- LLM
- LG Aimers 4th
- 해커톤
- GPT-4
- supervised learning
- 오블완
- LG
- 회귀
- PCA
- 머신러닝
- 딥러닝
- AI
- LG Aimers
- ChatGPT
- 분류
Archives
- Today
- Total
SYDev
[혼자 공부하는 자바] Chapter 8. 인터페이스 본문
1. 인터페이스 역할
- 인터페이스(Interface): 사전적인 의미로 두 장치를 연결하는 접속기, 두 장치를 객체로 본다면 두 객체를 연결하는 역할
- 주로 다형성 구현하는 경우
-> 객체 B가 객체 C로 변경됐을 때, 객체 B를 직접 호출하는 코드의 경우에는 객체 C를 호출하는 구조로 변경해줘야 함
-> 인터페이스를 사용하는 경우 이런 불필요함 X
2. 인터페이스와 구현 클래스 선언
- 인터페이스는 .java 형태의 소스파일로 작성, .class 형태로 컴파일되기 때문에 물리적 형태는 클래스와 동일
- but, 소스를 작성할 때 선언하는 방법과 구성 멤버가 다름
2.1. 인터페이스 선언
- 접근 제한자
- 같은 패키지 내에서만 사용 가능한 default
- 패키지와 상관 없이 사용하는 public
interface 인터페이스명 { ... } // default 접근 제한
public interface 인터페이스명 { ... } // public 접근 제한
- 인터페이스 멤버
public interface 인터페이스명 {
// public 상수 필드
// public 추상 메소드
// public 디폴트 메소드
// public 정적 메소드
// private 메소드
// private 정적 메소드
}
- 인터페이스 예제
package ch8.sec2;
public interface RemoteControl {
// public 추상 메소드
public void turnOn();
}
2.2. 구현 클래스 선언
- 객체 A가 인터페이스의 추상 메소드를 호출하면, 객체 B의 메소드를 실행
- 객체 B는 인터페이스에 선언된 추상 메소드와 동일한 선언부를 가징 메소드를 가지고 있어야 함
- 이때 객체 B를 인터페이스를 구현한(implement) 객체라 부름
public class B implements 인터페이스명 { ... }
-> 인터페이스를 구현하고 있음을 선언부에 명시해야 함
-> implements 키워드: 인터페이스를 통해 해당 클래스를 사용 가능하다는 뜻
- 예제
package ch8.sec2;
public class Television implements RemoteControl {
@Override
public void turnOn() {
System.out.println("TV를 켭니다.");
}
}
2.3. 변수 선언과 구현 객체 대입
- 인터페이스도 하나의 타입 -> 변수의 타입으로 사용 가능
- 인터페이스는 참조 타입 -> null 대입 가능
RemoteControl rc;
RemoteControl rc = null;
- 인터페이스를 통해 구현 객체를 사용하려면, 인터페이스 변수에 구현 객체를 대입해야 함 (주소 매칭)
rc = new Television();
rc.turnOn();
- 예제
package ch8.sec2;
public class TelevisionExample {
public static void main(String[] args) {
RemoteControl rc = new Television();
rc.turnOn();
rc = new Audio();
rc.turnOn();
}
}
3. 상수 필드
- 인터페이스에 선언된 필드는 모두 상수 필드 특성을 가지기 때문에, 생략 가능 -> 자동적으로 컴파일 과정에서 추가
- 상수 필드는 구현 객체와 관련 없는 interface 소속 멤버이므로, 인터페이스로 바로 접근해서 읽기 가능
[ public static final ] 타입 상수명 = 값;
4. 추상 메소드
- 마찬가지로 생략하더라도 컴파일 과정에서 자동으로 추가
- 인터페이스의 추상 메소드는 기본적으로 public 접근 제한을 가짐 > public보다 더 낮은 접근 제한으로 재정의 불가능
[ public abstract ] 리턴타입 메소드명( 매개변수, ... );
5. 디폴트 메소드
- 인터페이스에는 완전한 실행 코드를 가진 디폴트 메소드 선언 가능
- 추상 메소드와 달리 실행부( { ... } ) 존재
- 재정의 시, public 접근 제한자를 반드시 붙이고, default 키워드를 생략해야 한다.
[ public ] default 리턴타입 메소드명( 매개변수, ... ) { ... }
6. 정적 메소드
- 정적 메소드는 구현 객체 없이도 인터페이스만으로 호출 가능
- 접근 제한자 생략 시에 public이 자동으로 컴파일 과정에서 추가됨
[ public | private ] static 리턴타입 메소드명( 매개변수, ... ) { ... }
7. private 메소드
- 인터페이스의 상수 필드, 추상 메소드, 디폴트 메소드, 정적 메소드는 모두 public 접근 제한을 가짐
- 인터페이스에 외부에서 접근할 수 없는 private 메소드 선언 가능
- 디폴트 메소드, 정적 메소드 안에서만 호출 가능
- 중복 코드를 줄이기 위한 용도
- private method: 구현 객체 필요, private static method: 구현 객체 필요 X
package ch8.sec7;
public interface Service {
// default method
default void defaultMethod1() {
System.out.println("defaultMethod1 종속 코드");
defaultCommon();
}
default void defaultMethod2() {
System.out.println("defaultMethod2 종속 코드");
defaultCommon();
}
// private method
private void defaultCommon() {
System.out.println("defaultMethod 중복 코드A");
System.out.println("defaultMethod 중복 코드B");
}
// static method
static void staticMethod1() {
System.out.println("staticMethod1 종속 코드");
staticCommon();
}
static void staticMethod2() {
System.out.println("staticMethod2 종속 코드");
staticCommon();
}
// private static method
private static void staticCommon() {
System.out.println("staticMethod 중복 코드C");
System.out.println("staticMethod 중복 코드D");
}
}
package ch8.sec7;
public class ServiceImpl implements Service {
}
package ch8.sec7;
public class ServiceExample {
public static void main(String[] args) {
// 인터페이스 변수 선언과 구현 객체 대입
Service service = new ServiceImpl();
// call default method
service.defaultMethod1();
System.out.println();
service.defaultMethod2();
System.out.println();
// call static method
Service.staticMethod1();
System.out.println();
Service.staticMethod2();
System.out.println();
}
}
8. 다중 인터페이스 구현
- 구현 객체는 여러 개의 인터페이스를 implements 가능
- 구현 객체가 어떤 인터페이스 변수에 대입되느냐에 따라 변수를 통해 호출할 수 있는 추상 메소드가 결정됨
public class 구현클래스명 implements 인터페이스A, 인터페이스B {
// 모든 추상 메소드 재정의
}
인터페이스A 변수 = new 구현클래스명( ... );
인터페이스B 변수 = new 구현클래스명( ... );
9. 인터페이스 상속
- 인터페이스는 다른 인터페이스를 상속 가능, 클래스와 달리 다중 상속을 허용함
- 자식 인터페이스의 구현 클래스는 본인의 메소드뿐만 아니라, 부모 인터페이스의 모든 추상 메소드를 재정의해야 함
- 구현 객체는 자식 및 부모 인터페이스 변수에 대입될 수 있음
public interface 자식인터페이스 extends 부모인터페이스1, 부모인터페이스2 { ... }
- 구현 객체가 자식 인터페이스 변수에 대입 -> 자식 및 부모 인터페이스의 추상 메소드 모두 호출 가능
- 구현 객체가 부모 인터페이스 변수에 대입 -> 부모 인터페이스에 선언된 추상 메소드만 호출 가능
- 예제
package ch8.sec9;
public interface InterfaceA {
// abstract method
void methodA();
}
package ch8.sec9;
public interface InterfaceB {
// abstract method
void methodB();
}
package ch8.sec9;
public interface InterfaceC extends InterfaceA, InterfaceB {
// abstract method
void methodC();
}
package ch8.sec9;
public class InterfaceCImpl implements InterfaceC {
public void methodA() {
System.out.println("InterfaceCImpl-methodA() 실행");
}
public void methodB() {
System.out.println("InterfaceCImpl-methodB() 실행");
}
public void methodC() {
System.out.println("InterfaceCImpl-methodC() 실행");
}
}
package ch8.sec9;
public class ExtendExample {
public static void main(String[] args) {
InterfaceCImpl impl = new InterfaceCImpl();
InterfaceA ia = impl;
ia.methodA();
// ia.methodB();
// ia.methodC();
System.out.println();
InterfaceB ib = impl;
// ib.methodA();
ib.methodB();
// ib.methodC();
System.out.println();
InterfaceC ic = impl;
ic.methodA();
ic.methodB();
ic.methodC();
}
}
10. 타입 변환
- 인터페이스의 타입 변환은 인터페이스와 구현 클래스 간에 발생
- 인터페이스 변수에 구현 객체 대입 -> 구현 객체가 인터페이스 타입으로 자동 타입 변환
- 인터페이스 타입을 구현 클래스 타입으로 변환 -> 강제 타입 변환
10.1. 자동 타입 변환
인터페이스 변수 = 구현객체;
-> B, C, D, E로부터 생성된 객체는 모두 인터페이스 A로 자동 타입 변환 가능
10.2. 강제 타입 변환
구현클래스 변수 = (구현클래스) 인터페이스 변수;
-> 구현 클래스에 선언된 메소드 중, 인터페이스에 선언된 메소드만 사용 가능
-> setTime(), record()를 사용하고 싶으면 캐스팅 기호를 사용하여 원래 구현 클래스 타입으로 강제 타입 변환
- 예제
package ch8.sec10;
public interface Vehicle {
// 추상 메소드
void run();
}
package ch8.sec10;
public class Bus implements Vehicle {
// 추상 메소드 재정의
@Override
public void run() {
System.out.println("버스가 달립니다.");
}
// 추가 메소드
public void checkFare() {
System.out.println("승차요금을 체크합니다.");
}
}
package ch8.sec10;
public class CastingExample {
public static void main(String[] args) {
// 인터페이스 변수 선언과 구현 객체 대입 - 자동 타입 변환
Vehicle vehicle = new Bus();
vehicle.run();
// vehicle.checkFare();
// 인터페이스 변수 구현 클래스로 변환 - 강제 타입 변환
Bus bus = (Bus) vehicle;
bus.run();
bus.checkFare();
}
}
11. 다형성
- 메소드 재정의 + 자동 타입 변환 -> 다형성
- 인터페이스의 추상 메소드는 구현 클래스에서 재정의, 재정의되는 내용은 구현 클래스마다 다름
11.1. 필드의 다형성
- tire1, tire2 필드에 어떤 타이어 구현 객체가 대입되어도, Car 객체는 타이어 인터페이스에 선언된 메소드만 사용하므로 문제 X
package ch8.sec11;
public interface Tire {
// 추상 메소드
void roll();
}
package ch8.sec11;
public class HankookTire implements Tire {
// 추상 메소드 재정의
@Override
public void roll() {
System.out.println("한국 타이어가 굴러갑니다.");
}
}
package ch8.sec11;
public class KumhoTire implements Tire {
// 추상 메소드 재정
@Override
public void roll() {
System.out.println("금호 타이어가 굴러갑니다.");
}
}
package ch8.sec11;
public class Car {
// 필드
Tire tire1 = new HankookTire();
Tire tire2 = new HankookTire();
// 메소드
void run() {
tire1.roll();
tire2.roll();
}
}
package ch8.sec11;
public class CarExample {
public static void main(String[] args) {
// 자동차 객체 생성
Car myCar = new Car();
// run() 메소드 실행
myCar.run();
// 필드 교체
myCar.tire1 = new KumhoTire();
myCar.tire2 = new KumhoTire();
// run() 메소드 실행
myCar.run();
}
}
11.2. 매개변수의 다형성
- 매개변수 타입을 인터페이스로 선언하면, 메소드 호출 시 다양한 구현 객체 대입 가능
-> 어떤 구현 객체가 오더라도, 인터페이스에 선언된 메소드만 사용하므로 문제 X
12. 객체 타입 확인
- 상속에서 객체 타입 확인을 위해 사용한 instanceof 연산자를 인터페이스에서도 사용 가능
13. 봉인된 인터페이스
- sealed: permits 뒤에 위치한 interface만 interfaceA의 자식 인터페이스가 될 수 있음
- sealed 키워드를 사용한 경우, 자식 인터페이스인 InterfaceB는 non-sealed를 사용하여 선언하거나, sealed 키워드를 사용하여 또 다른 본인 인터페이스로 선언해야 함
public sealed interface InterfaceA permits InterfaceB { ... }
public non-sealed interface InterfaceB extends InterfaceA { ... }
참고자료
'Programming Lang > Java' 카테고리의 다른 글
[이것이 자바다] Chapter 11. 예외 처리 (0) | 2025.01.30 |
---|---|
[이것이 자바다] Chapter 9. 중첩 선언과 익명 객체 (0) | 2025.01.30 |
[혼자 공부하는 자바] Chapter 7. 상속 (0) | 2025.01.27 |
[혼자 공부하는 자바] Chapter 6. 클래스 (0) | 2025.01.23 |
[혼자 공부하는 자바] Chapter 5. 참조 타입 (1) | 2025.01.18 |