관리 메뉴

공부한것들을 정리하는 블로그 입니다.

JAVA8에 추가된 interface 기능(default method와 익명 구현 객체) 본문

JAVA/공부

JAVA8에 추가된 interface 기능(default method와 익명 구현 객체)

호 두 2017. 7. 30. 17:45
반응형


원글의 내용이 훌룡하여 

따로 부연설명은 적지 않겠습니다.





참고 : 

http://blog.eomdev.com/java/2016/03/30/default-method.html#






1. 자바8에서 인터페이스가 가질 수 있는 것들

1.1. 상수 필드(public static final)

    public interface Parent{
        public static final MAX_VALUE = 100;
        public static final MIN_VALUE = 0;
    }

1.2. 추상 메소드(public abstract)

    public interface Parent{
        // 상수 필드
        public static final MAX_VALUE = 100;
        public static final MIN_VALUE = 0;

        // 추상 메소드
        public abstract void run();
    }

1.3. 디폴트 메소드(public default)

    public interface Parent{
        // 상수 필드
        public static final MAX_VALUE = 100;
        public static final MIN_VALUE = 0;

        // 추상 메소드
        public abstract void run();

        // 디폴트 메소드 : 실행 내용까지 작성이 가능하다.
        public default void setState(boolean state){

            if(state){
                System.out.println("현재 상태는 정상입니다");
            }else{
                System.out.println("현재 상태는 비정상입니다");
            }

        }
    }

해당 인터페이스 구현시, 디폴트 메소드를 재정의(오버라이딩)해서 사용할 수 있다.

이 디폴트 메소드는 모든 구현 객체에서 공유하는 기본 메소드 용도로 사용할 수도 있지만, 더 유용하게 활용할 수 있다. 바로 이전에 개발한 구현 클래스를 그대로 사용하고 변경하지 않으면서, 새롭게 개발하는 클래스는 디폴트 메소드를 활용해 새로운 기능을 만들수 있는 것이다. 아래와 같이 인터페이스와 그 구현체가 존재한다고 가정해보자.

    public interface MyInterface{
        public abstract void method1();
    }
    public class MyInterfaceImplA implements MyInterface{

        public void method1(){
        // 구현 내용 
        }

    }

그런데 만약에 나중에 MyInterface에 새로운 기능을 추가해야되는 경우가 생긴다면, 기존에 해당 인터페이스의 구현체였던 MyInterfaceImplA에도 해당 메소드의 내용을 구현해줘야하는 문제점이 발생한다. 만약 MyInterfaceA를 수정할 여건이 안된다면 MyInterface에 새로운 추상 메소드를 추가할 수 없게 된다. 이런 경우 MyInterface에 디폴트 메소드를 선언하고, 필요에 따라서 새로 구현하는 구현체에서 디폴트 메소드를 재정의(오버라이딩)해서 구현해주면 된다.

    public interface MyInterface{
        public abstract void method1();
        // default method 선언
        public deafult void method2(){
            // 구현 내용
        }
    }
    // 기존에 있던 구현체들은 변경되는 내용 없음
    public class MyInterfaceImplA implements MyInterface{

        public void method1(){
        // 구현 내용 
        }

    }
    // 새로 생성된 구현체
    public class MyInterfaceImplB implements MyInterface{

        public void method1(){
        // 구현 내용 
        }

        @Override
        public void method2(){
            // 디폴트 메소드 재정의
        }

    }

1.4. 정적 메소드(public static)

    public interface Parent{
        // 상수 필드
        public static final MAX_VALUE = 100;
        public static final MIN_VALUE = 0;

        // 추상 메소드
        public abstract void run();

        // 디폴트 메소드 : 실행 내용까지 작성이 가능하다.
        public default void setState(boolean state){

            if(state){
                System.out.println("현재 상태는 정상입니다");
            }else{
                System.out.println("현재 상태는 비정상입니다");
            }

        }

        // 정적 메소드
        public static void change(){
            System.out.println("상태를 변경합니다.");
        }
    }

물론 사용할 때, Parent.change();와 같이 객체가 없어도 인터페이스만으로도 호출이 가능하다.

2. 인터페이스의 구현

2.1. 익명 구현 객체

해당 인터페이스의 구현체를 만들어서 사용하는 것이 일반적이고, 클래스를 재사용할 수 있기 때문에 편리하지만, 일회성의 구현 객체를 만들기 위해서는 비효율적이다. 자바8에서 지원하는 람다식은 인터페이스의 익명 구현 객체를 생성할 수 있도록 추가되었다. UI프로그래밍에서 이벤트를 처리하거나, 임시 작업 스레드를 만들기 위해서 유용하게 사용될 수 있다.

아래와 같은 방법으로 사용한다.

    인터페이스 변수 = new 인터페이스(){
        // 인터페이스에 선언된 추상 메소드의 실제 메소드 선언        
    };

ex)

    public class Example{
        public static void main(String[] args){

            Parent parent = new Parent(){
                public void run(){
                    // 실제 구현 내용
                }
            };

        }
    }

익명 구현 객체도 Example.java 컴파일시 Example$1.class와 같이 이름뒤에 $가 붙고 생성 번호가 붙는 class 파일이 생성된다.

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

    public class Child implements Parent1, Parent2 {
        // Parent1에 선언된 추상 메소드의 실제 메소드 선언 및 구현
        // Parent2에 선언된 추상 메소드의 실제 메소드 선언 및 구현
    }

3. 타입변환

3.1. 자동 타입 변환(Promotion)

인터페이스 변수 = new 구현체(); 의 경우

ex) Car car = new Bus();

3.2. 강제 타입 변환(Casting)

구현 객체가 인터페이스 타입으로 자동 타입 변환 되는 경우, 인터페이스에 선언된 메소드만 사용이 가능하다. 만약에 구현 클래스에 선언된 필드와 메소드를 사용해야 하는 경우에는 강제 타입 변환을 이용하여 다시 구현 클래스 타입으로 변환해야한다.

구현클래스 변수 = (구현클래스)인터페이스변수;

ex) Bus bus = (Bus)car;

3.3. 객체 타입 확인(instanceof)

강제 타입 변환시 instanceof 연산자로 확인하고 안전하게 강제 타입 변환을 할 것.

    if(car instanceof Bus){
        Bus bus = (Bus)car;
    }

4. 인터페이스 상속

클래스와 달리 다중 상속이 가능하다.

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



반응형
Comments