[자바 스터디] 8주자 과제: 인터페이스

yunu·2022년 5월 23일
0
post-thumbnail

8주자 과제: 인터페이스

목표

자바의 인터페이스에 대해 학습하세요.

학습할 것

  • 인터페이스 정의하는 방법
  • 인터페이스 구현하는 방법
  • 인터페이스 레퍼런스를 통해 구현체를 사용하는 방법
  • 인터페이스 상속
  • 인터페이스의 기본 메소드 (Default Method), 자바 8
  • 인터페이스의 static 메소드, 자바 8
  • 인터페이스의 private 메소드, 자바 9

인터페이스 정의하는 방법

인터페이스

  • 오로지 추상 메소드와 상수만을 포함
  • 추상 클래스는 추상 메소드뿐만 아니라 생성자, 필드, 일반 메소드를 포함
  • 접근제어자가 public abstract만 가능, Java8 이후 default method, static method, private method가 가능
  • 객체의 상태가 아닌 오로지 행동(기능)만을 지정해줄 수 있어 더 객체지향적인 프로그래밍을 할 수 있음 (기능에 대한 명세 집합)
  • 추상 클래스는 is - a : ~는 ~이다. (상태+기능 포함)
  • 인터페이스는 has - a : ~는 ~ 를 할 수 있다. (기능만 포함)

인터페이스를 사용하는 이유

  • 한 객체가 여러 기능을 가지고 있다면 인터페이스의 다중 상속을 이용해서 구현할 수 있고 만약 새로운 기능이 추가된다 하더라도 기존 구상 클래스에서 새로운 인터페이스를 상속받게하면 기존 코드의 변경없이 상속받은 인터페이스의 추상 메소드를 오버라이딩하여 빠르게 기능을 추가해 줄 수 있음
  • 다형성을 최대한으로 사용하여 코드의 수정을 줄이고 유지보수성을 높임
  • 클래스 간의 결합도를 낮춤

인터페이스 정의

// 접근제어자는 public 또는 default
(접근제어자) interface 인터페이스명 extends 인터페이스명1, 인터페이스명2 {
	// public static final는 생략 가능
	public static final (타입) 상수 =; // 상수명은 대문자로 표현
	
    // public abstract 생략 가능
    public abstract (타입) 추상메소드명(매개변수...); // 
	
    /***************** [JAVA 8 이후] *****************/
    
    // 추상 메소드가 아닌 구현체를 포함한 메소드
    // 추상 메소드가 아니더라도 구상 클래스에서 오버라이딩 할 수 있음
    (public) default (타입) 디폴트메소드명(매개변수...) { ... } // public은 생략됨
    
    // 구상클래스에서 오버라이딩 할 수 없음
    (public) static (타입) 정적메소드명(매개변수...) { ... } // public은 생략됨
    
    /***************** [JAVA 9 이후] *****************/
    
    // 디폴트 메소드의 로직을 구현하기 위한 내부 메소드
    private (타입) 메소드명(매개변수...) { ... }
    
    // 정적 메소드의 로직를 구현하기 위한 내부 메소드
    private static (타입) 메소드명(매개변수...) { ... }
}

인터페이스를 이용한 전역상수, 전역 정적메소드 선언하기

interface Friend {
	String NAME = "manu"; // public static final 생략되어 있음
    String AGE = "16"; // public static final 생략되어 있음
    
    static String info() {
    	System.out.println(NAME + ", " + AGE);
    }
}
...
Friend.NAME // == "manu"
Friend.AGE // == 16
Friend.info() // == "manu, 16"

인터페이스 구현하는 방법

구상 클래스를 이용하여 구현

/***************************[Pet.java]***************************/
public interface Pet {
	void beFriendly();
    void play();
}
/***************************[Dog.java]***************************/
public class Dog extends Canine implements Pet {
	@Override
    public void roam() { ... }
    @Override
    public void eat() { ... }
    
    @Override
    public void beFriendly() { ... }
    @Override
    public void play() { ... }
}

익명 구현 객체를 이용하여 구현

  • 익명 객체를 초기화한 지역의 지역변수를 사용 가능
String sound = "멍멍~!"
String food = "뼈다귀"

Pet pet = new Pet() {
	@Override
    public void roam() {
    	System.out.println(sound);
    }
    
    @Override
    public void eat() {
    	System.out.println(food);
    }
}; // expression의 일종으므로 끝에 세미클론 붙여야 됨

인터페이스 레퍼런스를 통해 구현체를 사용하는 방법

  • 구상 클래스 레퍼런스로 사용하지 않고 구상 클래스가 상속한 인터페이스 레퍼런스로 사용할 경우, 인터페이스의 기능만을 사용하도록 강제
Pet pet = new Dog();
// Pet 인터페이스의 메소드만 사용할 수 있음
pet.beFrendly();
pet.play();

// Dog 클래스에 roam(), eat() 메소드가 있지만 Pet 인터페이스로 참조했기 때문에 사용할 수 없음
pet.roam(); // error
pet.eat(); 	// error

인터페이스 상속

  • 인터페이스 간의 상속은 extends 키워드 사용
  • 인터페이스와 클래스 간의 상속은 implements 키워드 사용

인터페이스는 다중상속이 가능한 이유

  • 인터페이스의 모든 메소드는 추상메소드이기 때문에 구현체가 없다. 그로인해 죽음의 다이아몬드 문제가 발생하더라도 충돌될 구현체가 없어 다중상속 가능
  • 하지만 같은 이름의 메소드일지라도 다른 반환 타입의 메소드이면 다중상속 불가능

인터페이스의 기본 메소드 (Default Method), 자바 8

기존 인터페이스에서 새로운 메소드를 추가하면 해줘야 하는 작업

  • 자바 8 이전 -> 해당 인터페이스를 상속받은 모든 구상 클래스에서 새로운 메소드 재정의
  • 자바 8 이후 -> 인터페이스에 default 메소드을 추가하여 상속 받은 구상 클래스에서 재정의없이 바로 사용가능

죽음의 다이아몬드

  • 인터페이스에 추상 메소드가 아닌 구현체를 가지는 기본 메소드가 생기게 되면 죽음의 다이아몬드 문제가 다시 발생 (인터페이스는 다중상속이 가능했기 때문)
// 죽음의 다이아몬드 해결하기 위해 애매한 메소드를 명시적으로 재정의해줘야 함
/***************************[Pet.java]***************************/
public interface Pet {
	void beFriendly();
    default void play() {
    	System.out.println("play with pet");
    }
}
/***************************[Friend.java]***************************/
public interface Friend {
	void beFriendly();
    default void play() {
    	System.out.println("play with friend");
    }
}
/***************************[Dog.java]***************************/
public class Dog implements Pet, Friend {
    @Override
    public void beFriendly() { ... }
    @Override
    public void play() {
    	Pet.super.Play();		// 어떤 인터페이스의 메소드를 호출할지 모를때 명시적으로 재정의
        Friend.super.Play();	// 명시적으로 재정의하지 않을 시 컴파일 에러 발생!!
    }
}

인터페이스의 static 메소드, 자바 8

  • static 메소드는 재정의할 수 없음

인터페이스의 private 메소드, 자바 9

  • java 8 이후 default 메소드와 static 메소드 함에 따라 메소드 안의 중복적인 코드를 제거하고 캡슐화하기 위해 private 메소드 등장
  • 기존의 default 메소드와 static 메소드를 이용해서 중복적인 코드를 제거할 수 있지만 캡슐화되지 않아 외부에서 접근 가능하기 때문에 private 키워드로 보완

출처:
https://www.notion.so/8-0cc8c251d5374ac882a4f22fa07c4e6a
https://wikidocs.net/217
https://dev-coco.tistory.com/13
https://k3068.tistory.com/34
https://www.notion.so/4b0cf3f6ff7549adb2951e27519fc0e6
https://github.com/jongnan/java-study-with-whiteship/blob/master/week8/week8.md

profile
rip

0개의 댓글