목표
자바의 인터페이스에 대해 학습하세요.
학습할 것 (필수)
- 인터페이스 정의하는 방법
- 인터페이스 구현하는 방법
- 인터페이스 레퍼런스를 통해 구현체를 사용하는 방법
- 인터페이스 상속
- 인터페이스의 기본 메소드 (Default Method), 자바 8
- 인터페이스의 static 메소드, 자바 8
- 인터페이스의 private 메소드, 자바 9
인터페이스
- 다른 클래스를 작성할 때 기본이 되는 틀을 제공하면서, 다른 클래스 사이의 중간 매개체 역할까지 담당하는 추상 클래스보다 추상적인 추상 클래스를 의미한다
- 자바에서 추상 클래스는 추상 메소드뿐만 아니라 생성자, 필드, 일반 메소드도 포함될 수 있지만 인터페이스는 오로지 추상 메소드와 상수만을 포함할 수 있다.(JDK 1.8 이전)
인터페이스와 추상 클래스를 사용하는 이유
인터페이스랑 추상 클래스를 왜 사용해야하고 사용하면 뭐가 좋을까?
- 설계시 선언해 두면 개발할 때 기능을 구현하는 데에만 집중할 수 있다.
- 개발자의 역량에 따른 메소드의 이름과 매개 변수 선언의 격차를 줄일 수 있다.
- 공통적인 인터페이스와 abstract 클래스를 선언해 놓으면 , 선언과 구현을 구분할 수 있다.
인터페이스와 추상 클래스, 클래스의 차이
- 다시 한번 더 알아보자
인터페이스 정의하는 방법
인터페이스를 정의할 때는 접근제어자와 함께 interface
키워드를 사용하면된다
접근제어자 interface 인터페이스명 {
public static final 타입 상수이름 = 값;
타입 상수이름 = 값;
public abstract 메소드명(매개변수 );
}
클래스와 달리 인터페이스의 모든 필드는 public static final
이어야 하며 모든 메소드는 public abstract
이어야한다
인터페이스는 추상메서드와 정적 상수만 가질 수 있기에 따로 메서드에 public
과 abstract
필드에 public
, static
, final
을 붙이지 않아도 생략된 제어자는 컴파일 시 자바 컴파일러가 자동으로 추가해준다.
추가해주는지 확인을 해보자
예제
package LiveStudy._8Week;
public interface ITest {
int NON_STATIC_INT = 1;
public static final int STATIC_INT = 1;
public abstract void abstractMethod();
void nonAbstractMethod();
}
바이트 코드를 확인해 보자
// class version 55.0 (55)
// access flags 0x601
public abstract interface LiveStudy/_8Week/ITest {
// compiled from: ITest.java
// access flags 0x19
public final static I NON_STATIC_INT = 1
// access flags 0x19
public final static I STATIC_INT = 1
// access flags 0x401
public abstract abstractMethod()V
// access flags 0x401
public abstract nonAbstractMethod()V
}
컴파일러가 자동적으로 붙여준다.
그럼 제어자를 생략하는 것이 좋을까 명시해주는 것이 좋을까?
정답은 없고 모범답안은 있다. 스프링 입문을 위한 자바 객체 지향의 원리와 이해의 책을 보면 public static final, abstract 명시해주는거 추천한다. 인터페이스의 기본 규칙도 모르는 사람도 볼 수 있게 명확한 것이 좋다
인터페이스 구현하는 방법
- 인터페이스는 추상 클래스와 마찬가지로 자신이 직접 인스턴스를 생성할 수 없다
- 인터페이스가 포함하고 있는 추상 메소드를 구현해 줄 클래스를 작성해야만한다
class 클래스명 implements 인터페이스명 {...}
Animal interface
package LiveStudy._8Week;
public interface Animal {
public abstract void cry();
}
Cat
package LiveStudy._8Week;
public class Cat implements Animal{
@Override
public void cry() {
System.out.println("야옹");
}
}
Dog
package LiveStudy._8Week;
public class Dog implements Animal{
@Override
public void cry() {
System.out.println("멍멍!");
}
}
Sample
package LiveStudy._8Week;
public class InterfaceSample {
public static void main(String[] args) {
Cat cat = new Cat();
Dog dog = new Dog();
cat.cry();
dog.cry();
}
}
실행 결과
야옹
멍멍!
인터페이스 레퍼런스를 통해 구현체를 사용하는 방법
Animal
public interface Animal {
public abstract void cry();
}
Dog
public class Dog implements Animal{
@Override
public void cry() {
System.out.println("멍멍!");
}
public void name() {
System.out.println("Milk");
}
}
Cat
public class Cat implements Animal{
@Override
public void cry() {
System.out.println("야옹");
}
public void name() {
System.out.println("cream");
}
}
ReferenceSample
package LiveStudy._8Week;
public class ReferenceSample {
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();
dog.cry();
cat.cry();
// dog.name(); 사용 X
// cat.name(); 사용 X
((Dog)dog).name(); // 사용 O
((Cat)cat).name(); // 사용 O
}
}
결과
멍멍!
야옹
Milk
cream
인터페이스는 구현체를 통해서 인스턴스 생성이 가능하다
dog.name()
이 사용 못하는건 캐스팅을 안해줘서 사용을 못한다 dog가 바라보는 것은 Animal
인터페이스이다
사용하려면((Dog.)dog).name()
으로 캐스팅하여 사용이 가능하다
인터페이스 상속
자바는 다중 상속이 불가능한데 인터페이스는 다중 구현이 가능하다
인터페이스는 인터페이스부터만 상속을 받을 수 있다.
public interface extendsInterface extends Animal{
}
상속과 구현을 동시에 할 수 있다
class 클래스명 extends 상위클래스명 implements 인터페이스명 {...}
여러 인터페이스를 구현할 수 있다
public class implSample implements Animal, ITest{
@Override
public void cry() {}
@Override
public void abstractMethod() {}
@Override
public void nonAbstractMethod() {}
}
인터페이스의 기본 메소드 (Default Method), 자바 8
- java 8이 등장하면서
interface
에 대한 정의가 몇 가지 변경이 되었다 - 인터페이스가
default
키워드로 선언되면 메소드가 구현될 수 있다. 또한 이를 구현하는 클래스는default
메소드를 오버라이딩 할 수 있다.
특징
- interface 내에서 메소드 구현이 가능하다
- 참조 변수로 함수를 호출할 수 있다
- implements한 클래스에서 재정의가 가능하다
생긴 이유
- 인터페이스가 변경이 되면, 인터페이스를 구현하는 모든 클래스들이 해당 메소드를 구현해야 하는 문제가 있다. 이런 문제를 해결하기 위하여 인터페이스에 메소드를 구현해 놓을 수 있도록 하였다.
또 다른 이유로는 자바의 신의 내용을 인용하자면
(중략)바로 "하위 호환성"때문이다. 예를 들어 설명하자면, 여러분들이 만약 오픈 소스코드를 만들었다고 가정하자. 그 오픈소스가 엄청 유명해져서 전 세계 사람들이 다 사용하고 있는데, 인터페이스에 새로운 메소드를 만들어야 하는 상황이 발생했다. 자칫 잘못하면 내가 만든 오픈소스를 사용한 사람들은 전부 오류가 발생하고 수정을 해야 하는 일이 발생할 수도 있다. 이럴 때 사용하는 것이 바로 default 메소드다. (자바의신 2권 내용)
즉, 기존의 인터페이스를 강제 구현하지 않고 default 메소드를 추가해서 사용하면 프로그램에 영향이 없기 때문이다
default
method는 암시적으로public
이므로public
을 지정할 필요가 없다- 일반 인터페이스 메서드와 달리 메서드 시그니처 시작 부분에
default
키워드로 선언되며 구현을 제공한다
간단한 예
public interface Calculator {
int plus(int i , int j);
int multiple(int i, int j);
default int exec(int i, int j) {
return i + j;
}
}
- 인터페이스에 하나 이상의 구현이 있는 추상화를 기반으로 하는 일반적인 디자인에서 하나 이상의 메서드가 인터페이스에 추가되면 모든 메서드를 구현해야한다.
- default 인터페이스 방법은 이 문제를 처리하는 효율적인 방법이다.
인터페이스의 static 메소드, 자바 8
- Static Method는 Java8부터 추가되었다
- 특징
- interface에서 메소드 구현이 가능하다
- 반드시 클래스 명으로 메소드를 호출해야한다.
- 재정의 불가능
예제
Calculator
public interface Calculator {
int plus(int i , int j);
int multiple(int i, int j);
default int exec(int i, int j) {
return i + j;
}
public static int exec2(int i , int j) {
return i * j;
}
}
CalculatorImpl
package LiveStudy._8Week;
public class CalculatorImpl implements Calculator{
@Override
public int plus(int i, int j) {
return i + j;
}
@Override
public int multiple(int i, int j) {
return i * j;
}
}
CalculatorSample
public class CalculatorSample {
public static void main(String[] args) {
Calculator cal = new CalculatorImpl();
int value = cal.exec(1,2);
System.out.println(value);
int value2 = Calculator.exec2(1, 2);
System.out.println(value2);
}
}
실행 결과
3
2
- 인터페이스에 static 메소드를 선언함으로써, 인터페이스를 이용하여 간단한 기능을 가지는 유틸리티성 인터페이스를 만들 수 있게 되었다.
인터페이스의 private 메소드, 자바 9
- private method는 Java9부터 추가되었다
- private static method도 사용 가능하다
장점
인터페이스에서 캡슐화가 가능하다
인터페이스 내부의 코드 재사용성을 증가 시킨다
예를 들어 두 개의 default 메서드가 코드를 공유해야 하는 경우 private 인터페이스 메서드를 사용하면 가능하지만 해당 private method를 노출하지 않고 클래스를 구현한다
규칙
- private interface method는 추상화가 불가능하다
- private method는 인터페이스 내에서만 사용할 수 있다.
- private static method는 다른 static , non-static interface method 내에서 사용할 수 있다
- private non-static method는 private static method 내에서 사용 불가능하다( static 영역 때문)
예제
ExampleInterface
package LiveStudy._8Week;
public interface ExampleInterface {
public abstract void method1();
public default void method2() {
method4(); //private method 안의 default method
method5(); //static method 안의 다른 non-static method
System.out.println("default method");
}
public static void method3() {
method5(); //static method 안의 다른 static method
System.out.println("static method");
}
private void method4(){
System.out.println("private method");
}
private static void method5(){
System.out.println("private static method");
}
}
ExampleInterfaceSample
package LiveStudy._8Week;
public class ExampleInterfaceSample implements ExampleInterface{
@Override
public void method1() {
System.out.println("abstract method");
}
public static void main(String[] args) {
ExampleInterface exampleInterface = new ExampleInterfaceSample();
exampleInterface.method1();
exampleInterface.method2();
ExampleInterface.method3();
}
}
실행 결과
abstract method
private method
private static method
default method
private static method
static method
Reference
'스터디 > LiveStudy' 카테고리의 다른 글
10주차 과제: 멀티쓰레드 프로그래밍 (6) | 2021.01.18 |
---|---|
9주차 과제: 예외 처리 (0) | 2021.01.11 |
7주차 과제: 패키지 (0) | 2020.12.30 |
6주차 과제: 상속 (0) | 2020.12.21 |
5주차 과제: 클래스 (0) | 2020.12.19 |