티스토리 뷰
인터페이스
인터페이스(interface)는 객체의 사용 방법을 정의한 타입이다.
인터페이스는 자바의 다형성을 구현하는 매우 중요한 역할이다.
인터페이스란 클래스와 클래스 사이를 잇는 매개 역할이기도 하다.
인터페이스는 추상 클래스의 일종이기도 하지만 추상 클래스보다 추상화 정도가 높다.
인터페이스는 개발코드와 객체가 서로 통신하는 점점 역할을 한다.
개발 코드가 인터페이스의 메소드를 호출하면 인터페이스는 객체의 메서드를 호출시킨다.
그렇기 때문에 객체의 내부 구조를 알필요가 없고 인터페이스의 메서드만 알고 있으면 된다.
인터페이스는 일종의 약속 또는 사용명세서라고 할 수 있다. 인터페이스를 중간에 매개 역할로 사용하는 것은 이 인터페이스 안의 구현체가
어떻게 구현되어있는지는 몰라도 어떻게 동작할 것인지 어떻게 실행 될 것인지에 대한 약속인 것이다.
인터페이스 정의하는 방법
자바에서 인터페이스를 정의하는 방법
interface 인터페이스명 {
//상수
타입 상수명 = 값;
//추상 메소드
타입 메소드명(매개변수, ...);
//디폴트 메소드 자바8에서 추가
default 타입 메소드명(매개변수, ...) {...}
//정적 메소드 자바8에서 추가
static 타입 메소드명(매개변수, ...) {...}
}
인터페이스는 일반적인 자바의 클래스들과 몇가지 특징들이 있다.
- 모든 멤버변수는 public static final 이어야 하며, 이를 생략할 수 있다.
- 모든 메소드는 public abstract 이어야 하며, 이를 생략할 수 있다.
인터페이스 구현하는 방법
인터페이스도 추상클래스처럼 그 자체로는 인스턴스를 생성할 수 없으며 확장한다는 의미의 키워드 extends
가 아닌
구현한다는 의미의 키워드인 implements
를 사용한다.
class 클래스이름 implements 인터페이스이름 { ... }
예제
interface Animal {
void cry();
}
class Cat implements Animal {
public void cry() {
System.out.println("냐옹냐옹!");
}
}
class Dog implements Animal {
public void cry() {
System.out.println("멍멍!");
}
}
public class Polymorphism {
public static void main(String[] args) {
Cat c = new Cat();
Dog d = new Dog();
c.cry();
d.cry();
}
}
//결과
냐옹냐옹!
멍멍!
인터페이스 레퍼런스를 통해 구현체를 사용하는 방법
자바의 다형성을 보면 하나의 객체가 여러 가지 타입을 가질 수 있는 것을 의미한다.
자바에서는 이런 다형성을 부모 클래스 타입의 참조 변수로 자식 클래스 타입의 인스턴스를 참조할 수 있도록 하여 구현하고 있다.
인터페이스도 이를 구현한 클래스의 부모라고 할 수 있으므로 다형성의 특징을 활용해서 인터페이스를 타입으로써 사용할 수 있다.
interface Animal {
void cry();
}
class Cat implements Animal {
@Override
public void cry() {
System.out.println("냐옹냐옹!");
}
public void play() {
System.out.println("쥐 잡기 놀이하자~!");
}
}
class Dog implements Animal {
@Override
public void cry() {
System.out.println("멍멍!");
}
public void play() {
System.out.println("산책가자~!");
}
}
public class Polymorphism {
public static void main(String[] args) {
Animal cat = new Cat();
Animal dog = new Dog();
cat.cry();
dog.cry();
((Cat) cat).play();
((Dog) dog).play();
}
}
Animal 인터페이스 타입으로 cat과 dog를 선언하게 되면, Animal이 가질 수 있는 메서드만 사용할 수 있음을 알 수 있다.
play() 메서드는 캐스팅하여 사용해야 한다.
인터페이스 상속
인터페이스는 인터페이스로부터만 상속받을 수 있으며, 클래스와는 달리 다중 상속, 즉 여러 개의 인터페이스로부터 상속을 받는 것이 가능하다.
interface Animal {
void cry();
}
interface Pet {
void play();
}
class Cat implements Animal, Pet {
public void cry() {
System.out.println("냐옹냐옹!");
}
public void play() {
System.out.println("쥐 잡기 놀이하자~!");
}
}
class Dog implements Animal, Pet {
public void cry() {
System.out.println("멍멍!");
}
public void play() {
System.out.println("산책가자~!");
}
}
public class Polymorphism {
public static void main(String[] args) {
Cat c = new Cat();
Dog d = new Dog();
c.cry();
c.play();
d.cry();
d.play();
}
}
//결과
냐옹냐옹!
나비야~ 쥐 잡기 놀이하자~!
멍멍!
바둑아~ 산책가자~!
인터페이스 기본 메서드(default Method), 자바 8
인터페이스의 정의에도 써놨듯이 자바 8부터 추가된 default 메서드가 있다.
디폴트 메서드는 구현을 포함하는 메서드를 인터페이스에 정의할 수 있다.
인터페이스에서 디폴트 메소드를 허용한 이유는 기존 인터페이스를 확장해서 새로운 기능을 추가하기 위해서이다.
기존 인터페이스의 이름과 추상 메서드의 변경 없이 디폴트 메서드만 추가할 수 있기 때문에 이전에 개발한 구현 클래스를 그대로 사용할 수 있으면서 새롭게 개발하는 클래스는 디폴트 메서드를 활용할 수 있다.
인터페이스를 수정하거나 메서드를 추가할 일이 생겼을 때 default 메소드를 사용한다면 인터페이스를 구현한 구현클래스가 추가 구현을 할 필요가 없고 하위 호환성이 유지될 수 있다.
기존 인터페이스
public interface MyInterface{
void method1();
}
기존 구현 클래스
public Class MyClassA implements MyInterface {
@Override
public void method1() {
System.out.println("MyClassA-method1() 실행");
}
}
기존 인터페이스에 default 메소드를 추가
public interface MyInterface{
void method1();
default void method2() {
System.out.println("MyInterface default Method2")'
}
}
새로운 구현 클래스
public Class MyClassB implements MyInterface {
@Override
public void method1() {
System.out.println("MyClassA-method1() 실행");
}
@Override
public void method2() {
System.out.println("MyClassB-method2() 실행");
}
}
새로운 구현 클래스에서 디폴트 메소드를 재정의할 수도 있다. 그리고 인터페이스를 수정했음에도 컴파일 오류가 나지 않는다.
기존 구현클래스에서 MyClassA에서는 default 메서드를 강제적으로 구현하지 않아도 된다.
그리고 스프링 5와 스프링 부트 버전이 2.0으로 올라오면서 자바 8 버전 이상부터 필요하게 되었다.
이전 버전의 스프링 버전에서는 웹 애플리케이션을 구성하려면 WebMvcConfigurerAdapter 클래스를 사용했다.
(보통 자바에서 끝에 Adapter 가 붙는 클래스명들은 인터페이스를 구현한 추상 클래스이다.)
WebMvcConfigurerAdapter 추상 클래스는 WebMvcConfigurer 인터페이스의 모든 메서드를 구현하는 클래스이다.
이렇게 스프링 MVC 구성요소를 설정할 때 WebMvcConfigurerAdapter를 상속받아서 필요한 뷰 리졸버나 인터셉터 설정 메서드를 재정의할 수 있었는데 이제는 그럴 필요가 없어졌다.
왜냐하면? 자바 8부터 default 메서드가 생겼기 때문이다.
이전에는 인터페이스의 메서드를 모두 구현해야 했기 때문에 따로 추상 클래스를 만들어서 정말 꼭 구현해야 하는 메소드만 abstract 메서드로 정의해놓고 선택적으로 구현하는 메소드를 정의해놨지만 (이걸 템플릿 메소드 패턴이라고 한다.) 이제는 인터페이스에 default 키워드만 사용한다면 굳이 Adapter 추상클래스를 만들지 않아도 되기 때문이다.
실제 WebMvcConfigurer 인터페이스를 살펴보면 모두 default 메소드로 선언되어 있는 걸 확인할 수 있다.
public interface WebMvcConfigurer {
default void configurePathMatch(PathMatchConfigurer configurer) {
}
default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
}
default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
}
......
}
그리고 WebMvcConfigurerAdapter는 @Deprecated 되어 있는 것을 확인할 수 있다.
@Deprecated
public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {
...
}
인터페이스의 static 메서드, 자바 8
인터페이스 안의 static 메서드도 자바 8부터 추가되었는데 인스턴스 생성과 상관없이 인터페이스 타입으로 호출할 수 있는 메서드이다.
static 키워드를 사용하고, 접근제어자는 항상 public이며 생략할 수 있다.
public class StaticMethod {
public static void main(String[] args) {
List<String> list = List.of("1", "2");
for (String s : list) {
System.out.println("s = " + s);
}
}
}
인터페이스의 private 메서드, 자바 9
참고
www.yes24.com/Product/Goods/24259565?OzSrank=2
www.yes24.com/Product/Goods/15651484
- Total
- Today
- Yesterday
- 오라클
- config-location
- jQuery
- Spring Security
- Java
- maven
- mybatis config
- Mac
- Linux
- springboot
- k8s
- rocky
- window
- 북리뷰
- mybatis
- intellij
- localtime
- svn
- Spring
- LocalDateTime
- input
- Kotlin
- oracle
- Bash tab
- LocalDate
- Github Status
- 베리 심플
- JavaScript
- elasticsearch
- docker
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
29 | 30 | 31 |