ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java 인터페이스
    Java 2024. 2. 25. 15:20
    728x90
    반응형

    인터페이스(interface)


    일종의 추상 클래스, 추상클래스보다 추상화 정도가 더 높다. 추상클래스와 달리 몸통을 갖춘 일반 메서드 또는 멤버변수를 가질 수 없다.
    오직 추상메서드와 상수만을 멤버로 가진다
    인터페이스끼리만 상속 가능, 다중 상속 가능
        

    선언       

    interface 인터페이스이름{
        public static final 타입 상수이름 = 값;
        public abstract 메서드이름(매개변수 목록);
    }

     

    제약사항

            모든 멤버변수는 public static final, 생략 가능하다
            모든 메서드는 public abstract, 생략 가능. (jdk1.8부터 static과 디폴트메서드는 예외)
            생략된 제어자는 컴파일 시에 컴파일러가 자동으로 추가해준다
        

    구현

    class 클래스이름 implements 인터페이스이름{
        //추상메서드 구현하기
    }


    만일 구현하는 인터페이스 메서드 중 일부만 구현한다면 abstract를 붙여서 추상클래스로 만들어야 한다
    그리고 상속과 구현을 동시에 할 수 있다.
        

    인터페이스의 다중 상속       

    public class Tv{
        변수~~
    
        메서드~~
    }
    
    public class VCR{
        변수 ~~
    
        몸통 있는 메서드 ~~
    }
    
    public interface IVCR{
        몸통 없는 메서드~~
    }
    
    public class TVCR extends Tv implements IVCR{
        VCR vcr = new VCR();
    
        IVCR의 몸통없는 메서드(){
            vcr.VCR의 몸통있는 메서드();            << 코드 짜는 대신 VCR의 인스턴스 메서드 호출
        }
    }


    인터페이스 구현 없이 TVCR의 멤버 변수로 VCR 클래스를 포함시키는 것만으로도 충분하지만
    이렇게 만들면 인터페이스의 다형적 특성을 이용할 수 있다.

        

    인터페이스의 다형성

    Fightable f = new Fighter();
    
    >> 이용
    
    void attack(Fightable f){
        메서드 내용~~
    }
    
    리턴타입이 인터페이스인 경우도 있다.
    Fightable method(){
        ~~~
                Fighter f = new Fighter();
        return f;
    }


    리턴타입이 인터페이스라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미한다.
    위 코드에서는 Fightable를 구현한 Fighter 클래스의 인스턴스를 반환한다

        

    인터페이스 장점

            1. 개발 시간 단축
                메서드를 호출하는 쪽에서는 메서드 내용과 상관없이 선언부만 알면 된다.
                한 쪽에서는 인터페이스를 구현하는 클래스를 작성하게 되면,
                그 클래스가 작성될 때 까지 기다리지 않고도 반대쪽에서도 동시에 개발할 수 있다.

            2. 표준화 가능
                프로젝트에 사용되는 기본 틀을 인터페이스로 작성한 다음,
                개발자들에게 인터페이스를 구현하여 프로그램을 작성하도록 함으로써 보다 일관되고 정형화된 개발이 가능하다

            3. 서로 관계없는 클래스들에게 관계를 맺어줄 수 있다.

            4. 독립적인 프로그래밍 가능

            A클래스 - B클래스가 있을 때,
            B클래스의 methodB()의 선언부가 변경되면 이를 사용하는 A클래스도 변경되어야 한다

            하지만 A가 B를 직접 호출하지 않고 I를 통해 B에 접근하게 만들면 
            B에 변경사항이 생기거나 클래스 B와 같은 기능의 다른 클래스로 대체 되어도 A는 전혀 영향이 없다

            A클래스 - I인터페이스 - B클래스의 관계인 상태다

        

    인터페이스 예시

    class A{
        void autoPlay(I i){
            i.play();
        }
    }
    
    interface I {
        public abstract void play();
    }
    
    class B implements I{
        public void play(){
            sysout("play in B class");
        }
    }
    
    class C implements I{
        public void play(){
            sysout("play in C class");
        }
    }
    
    class interfaceTest2{
        public static void main(String args[]){
            A a = new A();
            a.autoPlay(new B());
            a.autoPlay(new C());
        }
    }


    위 코드에서 클래스 A의 작성에 클래스 B가 사용되지 않았다는 것이 핵심
    클래스 A가 인터페이스 I를 사용해 작성되었지만 매개변수를 통해 I를 구현한 클래스의 인스턴스를 동적으로 제공받아야 한다
            
        

    예시2

    class interfaceTest3{
        public static void main(String args[]){
            A a = new A();
            a.method();
        }
    }
    
    class A{
        void methodA(){
            I i = instanceManager.getInstance();
            i.methodB();
            sysout(i.toString());
        }
    }
    
    interface I{
        public abstract void methodB();
    }
    
    class B implements I{
        public void methodB(){
            sysout("methodB in B class");
        }
    
        public String toString(){
            return "class B";
        }
    }
    
    class instanceManager{
        public static I getInstance(){
            return new B();
        }
    }


    실행 결과
    >>

    methodB in B class
    class B
            
    인스턴스를 직접 생성하지 않고, getInstance라는 메서드를 통해 제공 받는다.
    이렇게 하면 나중에 다른 클래스의 인스턴스로 변경되어도 A클래스 변경 없이 getInstance만 변경하면 된다
        
        

    추가

    원래 인터페이스에 추상메서드만 선언할 수 있었는데
    jdk1.8부터 디폴트메서드와 static메서드도 추가할 수 있게 되었다.

    근데 static 메서드는 인스턴스랑 상관없는 독립적인 메서드라 원래부터 추가하지 못할 이유가 없었는데,
    자바를 쉽게 배우게 하도록 규칙을 단순히 할 필요가 있어서 모든 메서드는 추상메서드여야 한다는 규칙에 예외를 두지 않았다.
    그리고 이걸 사용하면 클래스 대신에 인터페이스를 사용하는 의미가 없어져서 비추

            

    디폴트 메서드

    조상 클래스에 새로운 메서드를 추가하는 것은 별 일이 아니지만, 인터페이스는 큰 일이다.
    인터페이스를 구현한 모든 클래스들이 새로운 메서드를 구현해야 하기 때문

    인터페이스가 안바뀌면 제일 좋지만 아무리 잘 만들어도 변경이 생길 수 밖에 없다
    그래서 고심 끝에 디폴트 메서드를 생각해냈다

    추상 메서드의 기본적인 구현을 제공하는 메서드로, 
    추상 메서드가 아니기 때문에 디폴트 메서드가 새로 추가되어도 해당 인터페이스를 구현한 클래스를 변경하지 않아도 된다.

    키워드로 default를 사용하며, 추상 메서드와 달리 일반 메서드처럼 몸통({})이 있어야 한다.
    접근 제어자는 public으로 생략 가능하다

    예시

    interface MyInterface{
        void method();
        void newMethod();                   << 추상 메서드
    }
            >>
    interface MyInterface{
        void method();
        default void newMethod(){}          << 디폴트 메서드
    }


                                

    대신 새로 추가된 디폴트 메서드가 기존의 메서드와 이름이 중복되어 충돌하는 경우가 발생한다. 이 충돌을 해결하는 규칙은 다음과 같다.

     

    1. 여러 인터페이스의 디폴트 메서드간의 충돌
    >> 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩 해야 한다
                    
    2. 디폴트 메서드와 조상 클래스의 메서드 간에 충돌
    >> 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.

    이 규칙을 외우기 귀찮으면, 그냥 필요한 쪽의 메서드와 같은 내용으로 오버라이딩 해버리면 그만이다.

    728x90
    반응형

    'Java' 카테고리의 다른 글

    Java java.lang - 1, Object 클래스  (1) 2024.02.25
    Java 예외 처리  (1) 2024.02.25
    Java 클래스의 다양한 형태(추상 클래스, 내부 클래스, 익명 클래스)  (1) 2024.02.25
    Java 제어자  (0) 2024.02.25
    Java Import  (0) 2024.02.25
Designed by Tistory.