8주차 과제: 인터페이스

2021. 1. 8. 23:10[WhiteShip]Java

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

1.인터페이스 정의하는 방법


인터페이스 선언

인터페이스는 '~.java'형태의 소스 파일로 작성되고 컴파일러(javac)를 통해 '~.class'형태로 컴파일되기 때문에 물리적 형태는 클래스와 동일합니다. 그러나 소스를 작성할 때 선언하는 방법이 다릅니다.

[public] interface 인터페이스이름{...}

인터페이스 이름은 클래스 이름을 작성하는 방법과 동일합니다. 영어 대소문자를 구분하며, 첫 글자를 대문자로 하고 나머지는 소문자로 작성하는 것이 관례입니다.

클래스는 필드, 생성자, 메소드를 구성 멤버로 가지는데 비해, 인터페이스는 상수 필드와 추상 메소드만을 구성 멤버로 가집니다.

interface example{
	//상수
    타입 상수이름 = 값;
    //추상 메소드
    타입 메소드이름(매개변수,...);
}
상수필드 선언

상수는 인터페이스에 고정된 값으로 실행 시에 데이터를 바꿀 수없다.

[public static final] 타입 상수이름 = 값;

->public static final은 생략가능하다.

추상 메소드 선언

인터페이스를 통해 호출된 메소드는 최종적으로 객체에서 실행된다.

인터페이스의 메소드는 실행 블록이 필요없는 추상 메소드로 선언한다.

[public abstract] 리턴타입 메소드이름(매개변수,...);

 

2.인터페이스 구현하는 방법


개발 코드가 인터페이스 메소드를 호출하면 인터페이스는 객체의 메소드를 호출한다. 객체는 인터페이스에서 정의된 추상 메소드와 동일한 메소드 이름, 매개타입, 리턴 타입을 가진 실체 메소드를 가져야만 한다. 이러한 객체를 인터페이스의 구현객체라고 하고, 구현 객체를 생성하는 클래스를 구현클래스라고 한다.

구현 클래스

인터페이스 타입으로 사용할 수 있음을 알려주기 위해서 클래스 선언부에 implements 키워드를 추가하고 인터페이스 이름을 명시해야한다.그리고 인터페이스에 선언된 추상 메소드의 실체 메소드를 선언해야 한다.

public class 구현클래스이름 implements 인터페이스이름{
}

 

다중 인터페이스 구현 클래스

객체는 다수의 인터페이스 타입으로 사용할 수 있다.

public class 구현클래스이름 implements 인터페이스A,인터페이스B{}

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


public class MyClass{
	//필드
	RemoteControl rc = new Television(); //1
    
    //생성자
    MyClass(RemoteControl rc){  //2
    	this.rc =rc;
    }
    
    //메소드
    void methodA(){
    	//로컬변수
        RemoteControl rc = new Audio();  //3
    }
}

1.인터페이스가 필드 타입으로 사용될 경우, 필드에 구현 객체를 대입할 수 있다.

MyClass myClass = new Myclass();
myClass.rc.turnOn();

2.인터페이스가 생성자의 매개 변수 타입으로 사용될 경우, new 연산자로 객체를 생성할 때 구현 객체를 생성자의 매개값으로 대입할 수 있다.

MyClass(RemoteControl rc){
	
    this.rc=rc;
    rc.turnOn();
}

3.인터페이스가 로컬 변수 타입으로 사용될 경우, 변수에 구현 객체를 대입할 수 있다.

void methodA(){

	RemoteConrtol rc = new Audio();
    rc.turnOn()
}

 

4.인터페이스 상속


인터페이스 또한 다른 인터페이스를 상속할 수 있으며 클래스와 다르게 다중 상속을 허용합니다.

public interface 하위인터페이스 extends 상위인터페이스1,상위인터페이스2{}

하위 인터페이스를 구현하는 클래스는 하위 인터페이스의 메소드뿐만 아니라 상위 인터페이스의 모든 추상 메소드에 대한 실체 메소드를 가지고 있어야 합니다. 그렇기 대문에 구현 클래스로부터 객체를 생성한 후에 다음고 같이 하위 및 상위 인터페이스 타입으로 변환이 가능합니다.

하위인터페이스 변수 = new 구현클래스(...);
상위인터페이스1 변수 = new 구현클래스(...);
상위인터페이스2 변수 = new 구현클래스(...);

하위 인터페이스로 타입 변환이 되면 상위 및 하위 인터페이스에 선언된 모든 메소드를 사용할 수 있으나, 상위 인터페이스로 타입 변환되면 상위 인터페이스에 선언된 메소드만 사용 가능하고 하위 인터페이스에 선언된 메소드는 사용할 수 없습니다.

//상위 인터페이스

public interface InterfaceA{
	public void methodA();
}
//상위 인터페이스

public interface InterfaceB{
	public void methodB();
}
//하위 인터페이스

public interface InterfaceC implements InterfaceA, InterfaceB{
	public void methodC();
}
//하위 인터페이스 구현

public class ImplementationC implement InterfaceC{
	public void methodA(){
    	System.out.println("implementsC - methodA 실행");
    }
    public void methodB(){
    	System.out.println("implementsC - methodB 실행");
    }
    public void methodC(){
    	System.out.println("implementsC - methodC 실행");
    }
//호출 가능 메소드
	
public class Example{
	public static void main(String[] args){
    	ImplementatinonC impl = new ImplementationcC();
        
        InterfaceA ia = impl;
        ia.methodA();
        System.out.println();
        
        InterfaceB ib = impl;
        ib.methodB();
        System.out.println();
        
        InterfaceC ic = impl;
        ic.methodA();
        ic.methodB();
        ic.methodC();
    }
}

실행결과는 스스로 생각해보기!

 

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


Default Method를 왜 사용할까?

"하위 호환성"때문에 사용한다. 예를 들자면 인터페이스에 새로운 메소드를 추가해야하는 상황이 발생하였을 때 함부로 수정하면 다른 곳에서 오류가 발생하는 경우가 생긴다. 이때 Default Method를 통해서 해결가능하다.

interface ExampleA{
	
    //void print();
    
    default void printD(){
    	System.out.print("Hello Default");
    }
}
public class DefaultMethod implements ExampleA{
	
    //public void print(){
    //	System.out.println("Hello World");
    //}
}
public class Example(){

	public voids static main(String[] args){
     	DefaultMethod dm = new DefaultMethod();
      	//dm.print();
        dm.printD();
    }
}

//출력결과 : Hello Default

위 코드에서 볼 수 있듯이 print()와는 다르게 default로 선언된 printD()는 DefaultMethod 클래스에서  객체생성을 하지않아도 오류없이 구현이 가능하다.

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


static method는 method의 body도 implementation해야한다. 

public interface Example{
	
    static int A(){
    	return 1;
    }
    
    static int b(); //에러발생
}

Interface의 static method는 상속이 되지않는다. 그렇기에 interface에 접근해서 호출해야한다.

Example.A();

 

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


자바 8의 문제점

  • 단지 특정 기능을 처리하는 내부method 일뿐인데도 외부에 공개되는 public method로 만들었어야 했다.
  • interface를 구현하는 다른 interface 또는 class가 해당 method에 액세스하거나 상속 할수 있는것을 원하지 않는다.

이 문제를 private static method/ private method라는 기능을 통하여 해결한다.

//java 8

public interface ICustomerService {
 
  default void healthcare(String name) {
    register(name);
    System.out.println("-- get HealthCare Service.");
  }
 
  default void consult(String name) {
    register(name);
    System.out.println("-- get Consultation Service.");
  }
 
  default void register(String name) {
    System.out.println(name + " registers for customer service.");
  }
}
//java 9

public interface ICustomerService {
 
  default void healthcare(String name) {
    register(name);
    System.out.println("-- get HealthCare Service.");
  }
 
  default void consult(String name) {
    register(name);
    System.out.println("-- get Consultation Service.");
  }
 
  private void register(String name) {
    System.out.println(name + " registers for customer service.");
  }
}

중복코드를 피하고 interface에 대한 캡슐화가 가능하다.

참고사이트