자바의 인터페이스에 대해 학습하세요.
- 인터페이스 정의하는 방법
- 인터페이스 구현하는 방법
- 인터페이스 레퍼런스를 통해 구현체를 사용하는 방법
- 인터페이스 상속
- 인터페이스의 기본 메소드 (Default Method), 자바 8
- 인터페이스의 static 메소드, 자바 8
- 인터페이스의 private 메소드, 자바 9
인터페이스 정의하는 방법
- 자동적으로 상수와 추상 메소드가 선언된다.
- 멤버 변수에는 public static final이 자동으로 붙는다.
- 메소드에는 public abstract가 자동으로 붙는다.
- 형식적인 선언만 있고 구현은 없다.
interface 인터페이스 이름 {
public static final float pi = 3.14;
public void add();
}
인터페이스의 요소
상수
- 모든 변수는 상수로 변환
추상 메소드
- 모든 메소드는 추상 메소드로 구현
- 모든 메소드의 접근 지정자는 public 이며 생략 가능
디폴트 메소드 java 8
- 기본 구현을 가지는 메소드, 구현 클래스에서 재정의 할 수 있음
정적 메소드 java 8
- 인스턴스 생성과 상관 없이 인터페이스 타입으로 사용할 수 있는 메소드
private 메소드 java 9
- 인터페이스를 구현한 클래스에서 사용하거나 재정의 할 수 없음. 인터페이스 내부에서만 기능을 제공하기 위하여 구현하는 메서드
추상클래스와 인터페이스의 공통점과 차이점
공통점
- 자기 자신을 객체화할 수 없으며 다른 객체가 상속 (extends) , 구현 (implements)를 하여 객체를 생성할 수 있다.
- 상속 (extends) , 구현 (implements)한 하위 클래스에서는 상위에서 정의한 추상메서드를 반드시 구현해야 한다.
차이점
추상 클래스 | 인터페이스 |
일반 메소드 포함 가능 | 모든 메서드는 추상 메서드 자바 8 이후 default, static 메소드 추가 가능 |
다중상속 불가 | 다중상속 가능 |
상수, 변수 필드 포험 가능 | 상수필드만 포함 가능 |
추상클래스는 "is-a : ~는 ~이다" 의 개념이다.
인터페이스는 "has-a : ~는 ~를 할 수 있다." 의 개념이다.
인터페이스 구현하는 방법
- implements 키워드를 사용
- 인터페이스에 정의되어 있는 메소드를 필수적으로 구현해야 한다.
- 구현 시, 부모의 메소드보다 넓은 법위의 접근제어자를 사용해야 한다.
public class Cat implements Animal {
@Override
public String getName() {
return "고양이";
}
@Override
public int getLegs() {
return 4;
}
}
인터페이스와 다형성
- 인터페이스는 clinet code와 서비스를 제공하는 객체 사이의 약속
- 어떤 객체가 어떤 interface 타입이라 함은 그 interface가 제공하는 메서드를 구현했다는 의미
- Client는 어떻게 구현되었는지 상관없이 interface의 정의만을 보고 사용할 수 있다.
- 다양한 구현이 필요한 인터페이스를 설계하는 일은 매우 중요한 일이다.
인터페이스 레퍼런스를 통해 구현체를 사용하는 방법
- 다형성의 특징을 활용하여 인터페이스를 타입으로써 사용가능
public interface TestInterface {
void print();
}
class TestClass2 implements TestInterface {
@Override
public void print() {
System.out.println("Class1_override");
}
}
public class TestClass implements TestInterface{
@Override
public void print() {
System.out.println("Class_override");
}
public void TestClass1(TestInterface testInterface) {
testInterface.print();
}
public static void main(String[] args) {
TestInterface testInterface = new TestClass();
TestInterface testInterface2 = new TestClass2();
testInterface.print();
testInterface2.print();
TestClass testClass = new TestClass();
testClass.print();
}
}
//Class_override
//Class1_override
//Class_override
인터페이스 상속
- 서브 인터페이스는 수퍼 인터페이스의 메서드까지 모두 구현해야 한다.
- 인터페이스 레퍼런스는 인터페이스를 구현한 클래스의 인스턴스를 가리킬 수 있고,
해당 인터페이스에 선언된 메서드만 호출 할 수 있다. - 클래스가 상속하는 것과 동일하게 extends 키워드를 사용하여 인터페이스를 상속할 수 있다
인터페이스 다중 상속
- 클래스와 달리 다중 상속이 가능하다.
- 상위 인터페이스에 있는 메서드 중 메서드 명과 파라미터 형식은 같지만 리턴 타입이 다른 메서드가 있다면,
둘 중 어느것을 상속받느냐에 따라 규칙이 달라지게 되므로 다중 상속이 불가능하다.
인터페이스의 Default Method - 자바 8
기본 메소드
- 해당 인터페이스를 구현한 클래스의 어떠한 영향 없이 새로운 기능을 추가하는 방법
- 구현체가 모르게 추가된 기능이므로 그만큼의 리스크가 따른다.
컴파일 에러는 발생하지 않지만 특정한 구현체의 로직에 따라 런타임 에러가 발생할 수 있다.
문서화 필요 - Object가 제공하는 equals, hasCode 와같은 기본 메소드는 제공 불가
- 인터페이스를 상속받은 인터페이스에서 다시 추상 메소드로 변경할 수 없다.
public interface TestInterface {
default void defaultmethod() {
System.out.println("default");
}
}
public interface TestInterface3 extends TestInterface{
@Override
private void defaultmethod() { // 불가 - 에러
TestInterface.super.defaultmethod();
}
}
- 인터페이스 구현체가 default method를 재정의 할 수 있다.
하위 호환성
- 인터페이스에 기능을 추가해도 이 인터페이스를 상속한 클래스들이 깨지지 않게 하는 것
- default 메소드를 추가하면 하위 호환성은 유지하면서 인터페이스 보완을 진행할 수 있다.
클래스에서 두 인터페이스를 상속하는데 각 인터페이스에 같은 이름의 디폴트 메소드가 있다면?
public class Snake implements PrintableAnimal, Printer {
// ...
@Override
public void print() {
PrintableAnimal.super.print(); // PrintableAnimal의 print() 메소드 호출
Printer.super.print(); // Printer의 print() 메소드 호출
// 혹은 직접 구현...
}
}
인터페이스의 Static Method - 자바 8
- 객체 생성 없이 클래스 이름으로 메소드를 호출하는 것
- 구현체 클래스에서 인터페이스명.메소드명 으로 접근
- 구현체 클래스에서 오버라이딩이 불가능하다.
- 메소드의 구현체를 가지고 있다.
- 상속이 불가능하다.
interface In1 {
static void test() {
System.out.println("static method");
}
}
public class TestClass implements In1{
public static void main(String[] args) {
In1.test(); // 인터페이스명.메소드명으로 접근한다.
}
}
인터페이스의 Private Method - 자바 9
- 자바 8에서 추가 된 default, static 메소드는 인터페이스 메소드와 더불어 public으로 만들어야 했다.
- abstract로 선언할 수 없다.
- 해당 인터페이스 안에서만 사용이 가능하다.
- private static 으로 시작하는 메소드는 다른 메소드가 non-static 이든 static 이든 접근 가능하다.
- private만 적용된 메소드는 static 메소드 안에서는 사용할 수 없다.
public interface PrintableAnimal extends Animal, Comparable<PrintableAnimal> {
static String getDescription() {
return "출력기능이 있는 동물 인터페이스";
}
// 자신의 메소드를 기본 메소드로 구현
// private 메소드 사용
default void print() {
printName();
printLegs();
}
// private 메소드로 기본 메소드에서 사용할 로직 분리 1
private void printName() {
System.out.println("이름 : " + getName());
}
// private 메소드로 기본 메소드에서 사용할 로직 분리 2
private void printLegs() {
System.out.println("다리개수 : " + getLegs());
}
// Comparable 인터페이스의 메소드를 상속하여 기본 메소드 구현
@Override
default int compareTo(PrintableAnimal o) {
return getLegs() - o.getLegs();
}
default void otherDefaultMethod() {
System.out.println("other default method");
}
}
'Back-end > java' 카테고리의 다른 글
스터디 10주차 - 멀티쓰레드 프로그래밍 (0) | 2021.07.02 |
---|---|
스터디 9주차 - 예외 처리 (0) | 2021.07.01 |
스터디 7주차 - 패키지 (0) | 2021.07.01 |
스터디 6주차 - 상속 (0) | 2021.06.30 |
스터디 5주차 - 클래스 (0) | 2021.06.30 |