개발/Java Study
8주차 : 인터페이스
박비버
2021. 2. 15. 10:21
1. 인터페이스 정의하는 방법
- 일종의 추상 클래스
- 추상메서드와 상수만 멤버로 가질 수 있음,일반 메서드 또는 멤버 변수를 구성원으로 가질 수 없음
interface 인터페이스이름 {
public static final 타입 상수이름 = 값;
public abstract 메서드이름 (매개변수목록);
}
- 모든 멤버 변수는 public static final 이어야하며, 생략 가능
- 모든 메서드는 public abstract 이어야하며, 생략 가능 (static메서드와 default 메서드는 예외 JDK1.8부터)
2. 인터페이스 구현하는 방법
- 추상 클래스처럼 그 차제로는 인스턴스를 생성할 수 없음
- '구현한다' 의미의 implements 사용
class 클래스 이름 implements 인터페이스이름 {
// 인터페이스에 정의된 추상메서드 구현해야함
}
class Fighter implements Fightable {
public void move(int x, int y) {}
public void attack (Unit u) {}
}
- 메서드 중 일부만 구현한다면 abstract 붙여서
abstract class Fighter implements Fightable {
public void move(int x, int y) {}
}
- 상속과 구현을 동시에 할 수 있음
class Fighter extends Unit implements Fightable {
public void move(int x, int y) {}
public void attack(Unit u) {}
}
3. 인터페이스 레퍼런스를 통해 구현체를 사용하는 방법
1. 인터페이스를 이용한 다중상속
- 멤버 변수는 static만 정의할 수 있고, 조상클래스의 멤버 변수와 충돌하는 경우는 거의 없고 충돌한다 하더라도 클래스 이름을 붙여서 구분이 가능
- 추상 메서드는 구현 내용이 없으므로 조상클래스의 메서드와 선언이 일치하면 조상클래스의 메서드를 상속 받음
- 다중상속을 하고 싶다면 한쪽만 선택하여 상속 받고 나머지 한쪽은 클래스 내에 포함시켜서 내부적으로 인스턴스를 생성해서 사용 가능 (인터페이스 작성 안하고도 내부에 인스턴스 새로 생성하면 되긴 한데, 이렇게 사용하면 다형적 특징을 이용할 수 있음)
public class TV{
protected boolean power;
public void power() { power = ! power; }
}
public class VCR {
protected int counter;
public void play(){
}
}
public interface IVCR {
public void play();
}
public class TVCR extends Tv implements IVCR {
VCR vcr = new VCR();
public void play(){
vcr.play();
}
}
2. 인터페이스를 이용한 다형성
- 인터페이스 Fightable을 클래스 Fighter가 구현했을 때 다음이 가능
- 리턴타입이 인터페이스 라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미함
Fightable f = (Fightable) new Fighter();
Fightable f = new Fighter();
class Fighter extends Unit implements Fightable {
void attack (Fightable f) {
// ...
}
}
Fightable method() {
//...
Fighter f = new Fighter();
return f;
}
4. 인터페이스 상속
- 인터페이스는 인터페이스로부터만 상속받을 수 있음
- 다중상속 가능
interface Movable {
void move(int x, int y);
}
interface Attackable {
void attack(Unit u);
}
interface Fightable extends Movable, Attackable { }
5. 인터페이스의 기본 메소드 (Default Method), 자바 8
- 인터페이스의 메서드 추가 -> 이 인터페이스를 구현한 기존의 모든 클래스들이 새로 추가된 메서드를 구현해야함..
- 기본적인 구현을 제공하는 default method를 만듦
- default method만 추가하면 이 인터페이스를 구현한 클래스들이 변경하지 않아도 됨
- 메서드 앞에 default 붙임, 중괄호가 있는 구현부가 있어야 함
interface MyInterface {
void Method();
default void newMethod() {}
}
- default 메서드가 기존의 메서드와 이름이 중복되어 충돌 할수 있음..
- 여러 인터페이스의 디폴트 메서드 간의 충돌 -> 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩 해야함
- 디폴트 메서드와 조상 클래스의 메서드 간의 충돌 -> 조상 클래스의 메서드가 상속되고 디폴트는 무시됨
class DefaultMethodTest {
public static void main(String[] args) {
Child c = new Child();
c.method1();
c.method2();
MyInterface.staticMethod();
MyInterface2.staticMethod();
}
}
class Child extends Parent implements MyInterface, MyInterface2 {
public void method1() {
System.out.println ("method1() in child");
// 두 인터페이스에서 겹치는 default 메서드가 있는 경우,
// 반드시 오버라이딩 받아서 구현해야한다
}
}
class Parent {
public void method2() {
System.out.println ("method2() in Parent");
}
}
interface MyInterface {
default void method1() {
System.out.println ("method1() in MyInterface");
}
default void method2() {
System.out.println ("method2() in MyInterface");
}
static void staticMethod() {
System.out.println ("staticMethod() in MyInterface");
}
}
interface MyInterface2 {
default void method1() {
System.out.println ("method1() in MyInterface2");
}
static void staticMethod() {
System.out.println ("staticMethod() in MyInterface2");
}
}
// 출력결과
method1() in Child
method2() in Parent
staticMethod() in MyInterface
staticMethod() in MyInterface2
6. 인터페이스의 static 메소드, 자바 8
- static 메서드는 인스턴스와 관계가 없는 독립적인 메서드-> 인터페이스의 모든 메서드는 추상 메서드이어야해서 static 메서드는 별도의 클래스로 둠
- java.util.Collection 인터페이스와 관련된 static 메서드들은 java.util.Collections에 추가됨
7. 인터페이스의 private 메소드, 자바 9
- 내부에서만 사용하는 메소드인데도 public으로 만들어야 하는 불편함 해소
- 해당 메소드에 엑세스하거나 상속하는 것을 원하지 않는 경우가 있음
- 구현부를 가져야함 함
- 인터페이스 내부에서만 사용가능
- private static 메소드는 다른 static 메소드, static 아닌 메소드 둘 다 사용 가능
- static이 아닌 private 메소드는 private static 메소드에서 사용할 수 없음
- 코드의 중복을 피하고 인터페이스에 대한 캡슐화를 가능하게 함
출처
자바의 정석, 남궁 성 지음
www.notion.so/4b0cf3f6ff7549adb2951e27519fc0e6