목표
자바의 인터페이스에 대해 학습하기
학습할 것
- 인터페이스 정의하는 방법
- 인터페이스 구현하는 방법
- 인터페이스 레퍼런스를 통해 구현체를 사용하는 방법
- 인터페이스 상속
- 인터페이스의 기본 메소드 (Default Method), 자바 8
- 인터페이스의 static 메소드, 자바 8
- 인터페이스의 private 메소드, 자바 9
추상 클래스 : 추상 메소드(메소드 선언만 있는)외에 멤버 변수, 일반 메소드를 가질 수 있음
인터페이스 : 추상 메소드와 상수만을 가지는 추상 클래스 -> 다중 상속을 흉내 낼 수 있음
인터페이스 정의하는 방법
interface Man { // 인터페이스 선언
public long ONE_SECOND = 1000; // 상수 선언, 반드시 초기화
public long ONE_MINUTE = 60000;
public void wakeup(); // 추상 메소드 선언, 끝에 ';' 사용
}
- 인터페이스에 정의된 상수와 메소드의 접근 한정자는 'public'이 기본 (private, protected는 사용 불가)
- 항상 상속받은 클래스에서 사용되어야 하기 때문이다.
- 메소드는 구현 부분 없이 선언 부분만 정의 되어야 한다.
- 인터페이스 내에는 추상 메소드의 선언이 허용된다.
- 인터페이스를 포함하는 클래스는 인터페이스에 선언된 메소드를 반드시 public으로 선언해야 한다.
인터페이스 구현하는 방법
interface Man{ // 인터페이스 선언
public long ONE_SECOND = 1000;
public long ONE_MINUTE = 60000;
public void wakeUp();
public void sleep();
}
interface Worker{ // 인터페이스 선언
public long WORK_TIME = 8;
}
public class Sleeper implements Man{ // 두 개의 인터페이스 포함
public void wakeUp(){ // 메소드 오버라이딩
System.out.println("빨리 일어나세요!");
}
public void sleep(){ // 메소드 오버라이딩
System.out.println("빨리 잠드세요!");
}
}
- 인터페이스를 사용하기 위해서 implements 예약어를 사용한다.
- 클래스에서 인터페이스를 포함하는 경우 인터페이스에서 정의된 모든 메소드를 클래스 내에서 반드시 오버라이딩 하여야 한다.
- 클래스가 인터페이스를 포함하는 것을 상속의 개념으로 본다면, 클래스는 인터페이스를 다중 상속할 수 있다.
- 즉 하나의 클래스가 상위 클래스를 여러개 가질 수 없지만, 다수 개의 인터페이스를 포함하는 것은 가능
- 만약 클래스가 다수 개의 인터페이스를 포함한다면, 그 인터페이스에 선언된 모든 메소드를 오버라이딩 해야한다.
인터페이스로 구현 할 수 없는 것이 있기 때문에 여전히 abstract의 효용가치는 있다! (default, private.., spring security)
인터페이스 레퍼런스를 통해 구현체를 사용하는 방법
-> 인터페이스가 있을 때는 인터페이스 타입 기반으로 코딩해야한다
- 인터페이스도 (추상 클래스와 같이) 다형성을 구현하는 데 사용될 수 있다.
- 인터페이스를 포함하는 클래스를 작성할 경우, 인터페이스를 상위 클래스의 개념으로 취급하여 다형성 구현 가능.
- 인터페이스의 형의 객체 변수에 그 인터페이스를 포함하는 클래스의 객체를 배정하여 인터페이스에서 선언된 메소드에 접근 가능
- 다형성 측면에서는 인터페이스는 추상 클래스와 같은 형태로 사용된다.
abstract class Figure{ // 추상 클래스 선언
abstract void draw();
}
interface Shape{ // 인터페이스 선언
public void computeArea(double a, double b);
}
class Triangle extends Figure implements Shpae{ // 추상클래스와 인터페이스를 포함
void draw(){ // 메소드 오버라이딩
System.out.println("삼각형 그리기 기능");
}
public void computeArea(double a, double h){ // 메소드 오버라이딩
System.out.println("삼각형 넓이 : " + (a*h/2));
}
}
class Rectangle extends Figure implements Shape{
void draw(){
System.out.println("사각형 그리기 기능");
}
public void computeArea(double h, double v){
System.out.println("사각형 넓이 : " + (h*v));
}
}
class Polydraw{
public void pdraw(Figure f){
f.draw();
}
public void pcomputeArea(Shape s, double a, double b){
s.computeArea(a, b);
}
}
public class InterfaceTest{
public static void main(String args[]){
Polydraw p = new Polydraw();
Figure fg1 = new Triangle();
Figure fg2 = new Rectangle();
Shape sp1 = new Triangle(); // 인터페이스 형의 객체 변수에 클래스의 객체 배정
Shape sp2 = new Rectangle();
p.pdraw(fg1);
p.pcompute(sp1, 4, 4); // 인터페이스 형의 객체 변수를 이용하여 메소드 호출
p.pdraw(fg2);
p.pcompute(sp2, 4, 4);
}
}
/* output
삼각형 그리기 기능
삼각형 넓이 : 8.0
사각형 그리기 기능
사각형 넓이 : 16.0
*/
<조금 더 간단한 예제>
- Man 인터페이스의 구현체인 Sleeper 객체를 만든다.
- 구현된 Sleeper 객체에서 Man 인터페이스에 선언된 추상 메소드를 사용할 수 있다.
public class ManTest{
public static void main(String[] args) {
// Sleeper 객체를 Man 인터페이스 타입으로 선언
Man man = new Sleeper();
man.wakeUp();
man.sleep();
}
}
인터페이스 상속
- 인터페이스도 필요에 따라 다른 인터페이스로부터 상속받을 수 있다.
- 인터페이스의 상속은 예약어 'extends'를 사용한다.
- 인터페이스는 다중상속을 허용한다. (클래스는 다중상속이 허용되지 않는다)
- 다중상속이란 하나의 클래스가 둘 이상의 클래스를 동시에 상속하는 것을 의미
<클래스 다중상속 코드>
// IPTV는 TV이자 Computer이다
class TV{
public void onTV(){
System.out.println("영상 출력 중");
}
}
class Computer{
public void dateReceive(){
System.out.println("영상 데이터 수신 중");
}
}
class IPTV extends TV, Computer{ // compile ERROR! -> 자바는 다중상속 지원x
public void powerOn(){
dataReceive();
onTV();
}
}
class CompileErrorEx(){
public static void main(String args[]){
IPTV iptv = new IPTV();
iptv.powerOn();
TV tv = iptv;
Computer comp = iptv;
}
}
하나의 클래스가 둘 이상의 클래스를 동시에 상속하는 코드 -> 다이아몬드 상속이 일어날 수 있음

- 다이아몬드 상속이 구성되면
- Employee 클래스에 정의된 메소드를, TechMarketer 클래스에서 호출하는 경우에 문제 발생
- TechMarketer클래스는 Employee 클래스를 간접적으로 두 번 상속하기 때문에 호출할 메소드의 선택이 애매해지기 때문
- 그래서 자바는 다중상속을 지원하지 않게하여 문제를 제한한다.
<클래스 다중 상속 코드>를 변경하여 <인터페이스를 이용하여 상속하기>
// IPTV는 TV이자 Computer이다
interface TV{
public void onTV();
}
class TVImpl{
public void onTV(){
System.out.println("영상 출력 중");
}
}
interface Computer{
public void dateReceive();
}
class ComputerImpl{
public void dataReceive(){
System.out.println("영상 데이터 수신 중");
}
}
class IPTV implements TV, Computer{
ComputerImpl comp = new ComputerImpl();
TVImpl tv = new TVImpl();
public void dataReceive(){
comp.dataReceive();
}
public void onTV(){
tv.onTV();
}
public void powerOn(){
dataReceive();
onTV();
}
}
class MultiInterfaceEx(){
public static void main(String args[]){
IPTV iptv = new IPTV();
iptv.powerOn();
TV tv = iptv;
Computer comp = iptv;
}
}
/* output
영상 데이터 수신 중
영상 출력 중
*/
인터페이스의 기본 메소드 (Default Method), 자바 8
인터페이스는 선언만 가능하고 구현을 할 수 없지만, 인터페이스의 default method에서는 구현이 가능하다!
인터페이스의 default method
- 하위 호환성을 유지(기존 인터페이스를 유지)하면서 인터페이스에 새로운 메소드 추가 가능
- Java 8부터 사용되었다.
- 모든 인터페이스에 추가 가능
기존에 있던 Man 인터페이스에 새로운 기능 rest()를 추가하려 한다.
interface Man{
public void wakeUp();
public void sleep();
}
그렇다면 Man 인터페이스를 구현하는 '모든' 클래스에 rest()를 새로 구현해야 한다.
이때 default method를 사용하면, 인터페이스 내에서 구현이 가능하다.
interface Man{
public void wakeUp();
public void sleep();
default void rest(){
System.out.println("휴식 중입니다!");
}
}
인터페이스의 static 메소드, 자바 8
- 인터페이스의 static method도 Java 8부터 사용 가능해짐 (이전 버전에서는 허용되지 않음)
- 객체 없이 인터페이스로 바로 호출 가능
interface Man{
public void wakeUp();
public void sleep();
default void rest(){
System.out.println("휴식 중입니다!");
}
static void eat(){
System.out.println("밥 먹는 중입니다!");
}
}
public class TestMan{
public static void main(String args[]){
Sleeper sleeper = new Sleeper();
sleeper.rest(); // default method
Man.eat(); // static method
}
}
인터페이스의 private 메소드, 자바 9
- 어떠한 메소드를 구현 할때 더 복잡한 메소드를 만드는 것이 좋다.
- 그러한 코드는 재사용성, 유지, 이해하기가 더 쉬워지기 때문
- 보통 이러한 목적을 가진 private method는 외부에서 볼 수 없고, 사용할 수 없음
- Java 8에서는 인터페이스 내에서 private method를 만들 수 없지만,
- Java 9에서는 인터페이스 내에서 private method를 만들 수 있다.
Java 9에서 이러한 private method를 만들면 가지게 되는 특징은?
- method body가 있고, abstract가 아니다.
- static 이거나 non-static 이거나
- 구현한 클래스와 인터페이스는 상속되지 않음
- 인터페이스로부터 method를 호출 할 수 있음
interface finalInterface{
private static int static staticMethod(){
return 100;
}
private int nonStaticMethod(){
return 200;
}
}
참고
- Java in a Nutshell, Benjamin J.Evans David Flanagan
- 처음 시작하는 JAVA 프로그래밍, 김충석 저
- 난 정말 JAVA를 공부한 적이 없다구요, 윤성우 저
- www.vojtechruzicka.com/java-interface-history/
'Java Live Study' 카테고리의 다른 글
Live Study 12주차 : 애노테이션 (0) | 2021.02.06 |
---|---|
Live Study 9주차 : 예외 처리 (0) | 2021.01.16 |
Live Study 7주차 : 패키지 (0) | 2021.01.02 |
Live Study 6주차 : 상속 (0) | 2020.12.26 |
Live Study 5주차 : 과제 (0) | 2020.12.18 |