-
인터페이스BackEnd/자바 2021. 1. 9. 12:14
- class는 인터페이스를 implments 키워드를 통해 상속받을 수 있다. 하지만 인터페이스가 인터페이스를 상속할 땐 class 끼리 상속하는 것과 동일하게 extends 를 사용한다.
- 모든 멤버변수는 public static final 이어야 하며, 이를 생략할 수 있다.
- 모든 메서드는 public abstract 이어야 하며, 이를 생략할 수 있다.
- 인터페이스는 객체의 타입으로만 사용된다.
- 인터페이스에는 추상 메소드만 존재한다.자바8부터 default, static 으로 method 구현 가능- 인터페이스의 상수는 private으로 만들 수 없다자바 9 부터 private method, private static method 가능interface 안에서 default 와 static 으로 선언하면 메서드를 구현할 수 있다.
public interface Bank { public int MAX_INTEGER = 1000000; public void withDraw(int price) ; public void deposit(int price) ; default String Auth() { return "default Auth method"; } default int calculate(int a,int b) { return a+b; } public static int dormancyAcc() { System.out.println("static dormancyAcc"); return 30; } }
인터페이스를 상속하면 자동으로 ovverride 되는 메서스는 추상 메서드인 withDraw 와 deposit 만 나오지만
default 메서드인 Auth 도 override 를 할 수 있다.
또 override 한 deposit 안에서 default 인 calculate 도 호출해 사용해보고,
myBank 에서 가지고 있는 메서드에서 인터페이스 Bank 의 static 메서드인 dormacyAcc 를 호출해보기도 하였다.
public class myBank implements Bank { private int myacc = 1000; @Override public void withDraw(int price) { System.out.println("implements 하면 withDraw 만 자동 override"); System.out.println("Bank 에 있는 상수 " + MAX_INTEGER); } @Override public String Auth() { return Bank.super.Auth(); } @Override public void deposit(int price) { int value = calculate(price,myacc); //Bank 의 default 메서드 사용 System.out.println(value); } public void useStatic() { Bank.dormancyAcc(); //Bank 의 static 메서드 사용 } }
- 인터페이스가 변경이 되면, 인터페이스를 구현하는 모든 클래스들이 해당 메소드를 구현해야 하는 문제가 있다. 이런 문제를 해결하기 위하여 인터페이스에 메소드를 구현해 놓을 수 있도록 하였다.
- 인터페이스에 static 메소드를 선언함으로써, 인터페이스를 이용하여 간단한 기능을 가지는 유틸리티성 인터페이스를 만들 수 있게 되었다.
※ 다이아몬드 문제
다중 상속을 지원하게 되면 하나의 클래스가 여러 상위 클래스를 상속 받을 수 있다. 이런 특징 때문에 발생하게 되는 문제를 '다이아몬드 문제' 라고 한다.
GrandParent이라는 클래스가 myMethod() 라는 이름의 메소드를 가지고 있는데,
Father 와 Mother 가 이를 각각 상속받는다.
그런데 Father 와 Mother 둘 다 상속받은 Child 클래스 입장에서는 양쪽 부모에 동일한 메서드가 있기때문에 충돌이 발생한다.
기존 인터페이스에서는 기능만 선언하기 때문에 이런 문제가 발생할 여지가 없었지만 , default 로 메서드 내용을 선언할 수 있기 때문에 충돌할 수 있다.
=> 컴파일 오류
Duplicate default methods named ccc with the parameters () and () are inherited from the types Father and Mother
public interface GrandParent { default void myMethod(){ System.out.println("GrandParent"); }; } public interface Father extends GrandParent{ @Override default void myMethod(){ System.out.println("Father"); }; } public interface Mother extends GrandParent{ @Override default void myMethod() { System.out.println("Mother"); } } public class Child implements Mother,Father{ } => Duplicate default methods named ccc with the parameters () and () are inherited from the types Father and Mother
Child 에 GrandParent 와 Mother 를 implements 하고 myMethod 를 실행하니
Mother 에 있는 myMethod 가 실행되었다.
public interface GrandParent { default void myMethod(){ System.out.println("GrandParent"); }; } public interface Mother extends GrandParent{ @Override default void myMethod() { System.out.println("Mother"); } } public class Child implements GrandParent,Mother{ } public class Test { public static void main(String[] args) { Child c = new Child(); c.myMethod(); //Mother } }
자바 9부터 인터페이스 private method 와 private static method 구현이 가능하다. (private 변수는 안됨)
public interface Bank { private int calculate2(int a) { int interest = 300; return interest + a; } private static int calculate3(int a) { return a; } }
- 인터페이스 구현
- 인터페이스 Bank 를 클래스 myBank 의 타입으로 구현
public class Test { public static void main(String[] args) { Bank bank = new myBank(); bank.withDraw(1000); String auth = bank.Auth(); System.out.println(auth); int value = Bank.dormancyAcc(); System.out.println(value); } }
-인터페이스 직접 override 해서 구현
public class Test { public static void main(String[] args) { Bank bank = new Bank() { @Override public void withDraw(int price) { System.out.println("인터페이스 구현 withDraw"); } @Override public void deposit(int price) { System.out.println("인터페이스 구현 deposit"); } }; bank.withDraw(2000); bank.deposit(1000); } }
-인스턴스 레퍼런스와 클래스 타입 레퍼런스의 차이
public class myBank implements Bank { private int myacc = 1000; @Override public void withDraw(int price) { System.out.println("implements 하면 withDraw 만 자동 override"); System.out.println("Bank 에 있는 상수 " + MAX_INTEGER); } @Override public void deposit(int price) { int value = calculate(price); System.out.println(value); } public void useStatic() { Bank.dormancyAcc(); } }
Interface Bank 를 타입으로 구현하면 class myBank 에 구현한 메서드는 호출할 수 없고,
Bank 안에 있는 메서드만 가능하다.
하지만 class myBank 를 타입으로 구현하면 Bank와 myBank 에 구현한 메서드를 모두 사용 가능하다.
public class Test { public static void main(String[] args) { // 인스턴스 레퍼런스 Bank bank = new myBank(); bank.withDraw(1000); String auth = bank.Auth(); System.out.println(auth); bank.useStatic(); // useStatic is undefined for the type Bank System.out.println("------------------------------"); //클래스 타입 레퍼런스 myBank myBank = new myBank(); myBank.useStatic(); } }
출처:
programmers.co.kr/learn/courses/5/lessons/241
반응형'BackEnd > 자바' 카테고리의 다른 글
Enum (0) 2021.01.31 예외처리 (0) 2021.01.16 자바 기초 (패키지, import , classpath, 접근제어자) (0) 2021.01.01 중첩클래스의 쓰임 > 이펙티브 자바 아이템 24 (0) 2020.12.26 상속 , dynamic dispatch (0) 2020.12.26