ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [스터디 8주차] JAVA 인터페이스
    프로그래밍 언어/JAVA 2021. 6. 25. 16:24
    더보기

    목표: 자바의 인터페이스에 대해 학습

     

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

    자바에서 말하는 인터페이스는 객체의 사용 방법을 정의한 타입이다.

    인터페이스는 개발 코드와 객체가 통신하는 접점 역할을 한다. 개발 코드가 인터페이스의 메소드를 호출하면 인터페이스는 객체의 메소드를 호출시키기때문에 개발 코드는 객체의 내부 구조를 알 필요가 없어진다.

    그러면 그냥 새로운 객체를 생성해서 메소드를 직접 호출하면 되는데 왜 중간에 인터페이스를 만들어서 사용하는 것일까?

    인터페이스는 하나의 객체가 아니라 여러 객체들과 사용이 가능하다.

    여러 객체들과 사용이 가는하면 어떤 객체를 사용하느냐에 따라 실행 결과가 달라질 수 있고 개발 코드에서는 코드 변경 없이 실행 결과를 다양화할 수 있는 장점을 가지게 된다.

     

     

    그러면 인터페이스를 선언하는 방법은 어떻게 될까?

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

    인터페이스 이름은 영어 대소문자를 구분하며 첫 분자를 대문자로 하고 나머지는 소문자로 작성하는 것이 관례이다.

    ex) InnerSuit, RemoteControl...

    인터페이스의 구성 멤버는 상수메소드가 있다.

    interface 인터페이스명 {
    // 상수 필드(Constant Field)
    타입 상수명 = 값;
    
    // 추상 메소드(Abstract Method)
    타입 메소드명(매개변수, ...);
    
    // 디폴트 메소드(Default Method)
    default 타입 메소드명(매개변수,...) {...}
    
    // 정적 메소드(Static Method)
    static 타입 메소드명(매개변수, ...) {...}
    
    }

    - 상수 필드(Constant Field)

    인터페이스에는 런타임 시 데이터를 저장할 수 있는 필드는 선언할 수 없지만 상수 필드는 선언이 가능하다.

    상수는 고정된 값으로 런타임 시에 값을 바꿀 수 없고 상수를 선언할 때에 반드시 초기화해야한다.

    인터페이스에 선언된 필드는 모두 pubilc static final특성을 갖는다.

    따라서, 우리가 코드에 public static final을 명시해주지 않아도 자동으로 컴ㅍ일 과정에서 붙게 된다.

     

    - 추상 메소드(Abstract Method)

    추상 메소드는 객체가 가지고 있는 메소드를 설명하는 것으로 메소드 호출 시에 어떠한 매개값이 필요하고, 리턴 타입은 무엇인지만 알려준다.

    그래서 추상 메소드는 리턴 타입, 메소드명, 매개변수만 기술하고 어떠한 실행을 하는지에 대한 코드를 담는 중괄호는 존재하지 않는다.

    인터페이스에 선언된 추상 메소드는 모두 public abstract 특성을 갖는다.

     

    - 디폴트 메소드(Default Method)

    디폴트 메소드는 인터페이스에서 선언하지만 객체가 가지고 있는 인스턴스 메소드라고 생각해야한다.

    자세한 내용은 6. 인터페이스의 static 메소드, 자바 8에서 알아보자.

     

    - 정적 메소드(Static Method)

    정적 메소드는 디폴트 메소드와 달리 객체가 없어도 인터페이스만으로 호출이 가능한 메소드이다.

    자세한 내용은 5. 인터페이스의 기본 메소드 (Default Method), 자바 8에서 알아보자.

     

     

     

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

    개발 코드가 인터페이스 메소드를 호출하면 인터페이스는 객체의 메소드를 호출하기 위해 객체는 인터페이스에서 정의된 추상 메소드와 동일한 메소드 이름, 매개 타입, 리턴 타입을 가진 실제 메소드가 있어야한다.

    이러한 객체는 인퍼페이스의 구현(implement) 객체라 하고 구현 객체를 생성하는 클래스를 구현 클래스라고 한다.

     

    구현 클래스는 인터페이스 타입으로 사용할 수 있음을 알려주기 위해 클래스 선언부에 implement 키워드를 추가하여 인터페이스명을 명시한다.

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

     

    구현 클래스에서 추상 메소드에 대한 실체 메소드를 선언할 때 주의할 점이 있다.

    인터페이스의 모든 메소드(추상, 디폴트, 스태틱)는 기본적으로 public 접근 제한을 갖기 때문에

    실체 메소드에서 public보다 더 낮은 접근 제한(protected, default, private)으로 선언할 수 없다는 것이다.

    우리가 클래스에서 메소드를 선언 할때 접근 제한자를 생략하면 기본적으로 default 접근 제한을 가진다고 배웠다.

    그러므로, 구현 클래스에서 실체 메소드 선언 시에 public을 생략한다면 컴파일 에러가 난다.

     

     

    ☞ 익명 구현 객체

    위에서 말하는 추상 메소드의 실체 메소드 선언을 위해 구현 클래스 소스 파일을 만들고 클래스를 선언하는 것은 비효율적이다.

    굳이 인터페이스 소스 파일, 클래스 소스 파일을 다 만든다면 인터페이스를 안 쓰는 것이 노동의 시간으로 보면 효율적일 수도 있기 때문이다.

    그래서 자바에서는 소스 파일을 만들지 않고도 구현 객체를 만들수 있는 익명 구현 객체를 제공한다.

    익명 구현 객체를 만들어 인터페이스 변수에 대입하는 코드는 다음과 같다.

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

     

     

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

     

    public class 구현클래스명 implements 인터페이스A, 인터페이스B {
        // 인터페이스 A에 선언된 추상 메소드의 실체 메소드 선언
        // 인터페이스 B에 선언된 추상 메소드의 실체 메소드 선언
    
    }

    구현 객체가 반드시 하나의 인터페이스에 대해 실체 메소드를 정의하라는 법은 없다.

    두 인터페이스가 객체의 메소드를 호출할 수 있으려면 객체는 두 인터페이스를 모두 구현해야하는데 구현 클래스는 위 코드처럼 작성할 수 있다.

     

     

     

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

    인터페이스로 구현체(구현 객체)를 사용하는 방법은 다음과 같다.

    // 방법 1
    인터페이스 변수;
    변수 = new 구현 객체명;
    
    // 방법 2
    인터페이스 변수 = new 구현 객체명;

    여기서 알아두어야 할 점은 인터페이스 변수는 참조 타입(reference type)이기 때문에 구현 객체가 대입되면 구현 객체의 주소를 저장한다.

     

    이렇게 구현 객체가 인터페이스 타입에 대입되면 인터페이스에 선언된 추상 메소드를 호출할 수 있다.

    또한, 개발 코드에서 인터페이스는 클래스의 필드, 생성자, 메소드의 매개변수, 생성자 또는 메소드의 로컬 변수로 선언될 수 있다.

    public class ExampleClass {
        // 필드
        Control ctr = new computer();
        
        // 생성자
        ExampleClass( Control ctr) {
            this.ctr = ctr
        }
        
        // 메소드
        void method1() {
            //로컬 변수
            Control ctr = new Car();
        }
        
        void method2(Control ctr){
            ...
        }
    }

     

    ※ 만약에 인터페이스를 구현한 구현 클래스를 상속한 자식 클래스가 있다면 자식 객체도 인터페이스 구현체로 사용될 수 있다.

     

     

     

    4. 인터페이스 상속

    인터페이스도 클래스처럼 다른 인터페이스를 상속할 수 있다.

    클래스 상속과 다른 점은 다중 상속을 허용한다는 것이다.

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

    상속받은 하위 인터페이스는 자신이 선언한 추상 메소드뿐만 아니라 상위 인터페이스의 모든 추상 메소드에 대한 실체 메소드를 가지고 있어야 한다.

     

    이렇게 되면 하위 인터페이스의 구현 클래스로부터 객체를 생성하고 하위 인터페이스와 상위 인터페이스 타입의 변수에 대입이 가능하다.

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

    인터페이스 상속을 하면 알아두어야 할 점은

    하위 인터페이스 타입으로 선언된 변수로는 상위 인터페이스에서 선언된 모든 기본 메소드, 정적 메소드를 사용할 수 있다.

    하지만 상위 인터페이스 타입으로 선언된 변수로는 하위 인터페이스에는 선언됐지만 상위 인터페이스에서는 선언되지 않은 메소드를 호출할 수 없다.

     

     

    ☞ 디폴트 메소드가 있는 인터페이스를 상속하는 경우

    상위 인터페이스에 디폴트 메소드가 선언되었다면 하위 인터페이스에서 디폴트 메소드를 활용하는 방법은 세 가지가 있다.

    1. 디폴트 메소드를 단순히 상속받아 사용한다.

    2. 디폴트 메소드를 Override해서 실행문을 변경한다.

    3. 디폴트 메소드를 추상 메소드로 재선언한다.

     

     

     

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

    기본 메소드(Default Method)는 자바 8에서 추가된 인터페이스의 새로운 멤버이다.

    [public] default 리턴타입  메소드명(매개변수, ...) {

    }

    (public은 생략해도 자동으로 컴파일 과정에서 붙는다.)

    이러한 기본 메소드는 인터페이스에 선언되지만 인터페이스에서 바로 사용할 수 없다.

    기본 메소드는 추상 메소드가 아닌 인스턴스 메소드이므로 구현 객체가 있어야 사용할 수 있다.

    즉, 아래의 코드(line 16)처럼 기본 메소드를 호출할 수 없다는 것이다.

    1: public interface Control {
    2:	
    3: 	// 디폴트 메서드 (실행 내용까지 작성)
    4: 	public default void setMute(boolean mute) {
    5:		if(mute) {
    6:			System.out.println("무음 처리합니다.");
    7:		} else {
    8:			System.out.println("무음 해제합니다.");
    9:		}
    10:	}
    11:    
    12:}
    13:
    14:
    15:// 호출이 안되는 기본 메소드
    16:Control.setMute(true);
    

     

    기본 메소드를 호출하기 위해서는 인터페이스의 구현 객체가 필요하므로 아래와 같이 객체를 인터페이스 변수에 대입한 후 기본 메소드를 호출 할 수 있다.

    // computer라는 구현 클래스가 생성됐다고 가정.
    
    Control ctr = new Computer();
    ctr.setMute(true);

     

    기본 메소드는 인터페이스의 모든 구현 객체가 가지고 있는 메소드라고 생각하면 된다.

    하지만, 구현 객체들 중에서 기본 메소드의 실행문이 적절하지 않아 수정할 일이 발생할 수도 있다.

    이러한 경우에는 구현 클래스를 작성할 때 기본 메소드를 overriding해서 수정하면 된다.

    public class Computer implements Control {
        @override
        public void setMute(boolean mute) {
            this.mute = mute;
            if(mute) {
                System.out.println("Computer 무음 처리합니다.");
            } else {
                System.out.println("Computer 무음 해제합니다.");
            }
        }
    }

     

     

     

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

    정적 메소드(static 메소드)는 기본 메소드와 마찬가지로 자바 8에서 추가된 새로운 멤버이다.

    [public] static 리턴타입 메소드명(매개변수, ...) {

    }

    (public은 생략해도 자동으로 컴파일 과정에서 붙는다.)

    정적 메소드는 기본 메소드와 달리 인터페이스로 바로 호출이 가능하다.

     public interface Control {
    	
    	// 디폴트 메서드 (실행 내용까지 작성)
     	public default void setMute(boolean mute) {
    		if(mute) {
    			System.out.println("무음 처리합니다.");
    		} else {
    			System.out.println("무음 해제합니다.");
    		}
    
        }
        
        // static 메소드
        static void changeBettery() {
    		System.out.println("건전지를 교환합니다.");
    	}
        
    }
    
    
    // 바로 호출이 가능한 static 메소드
    Control.changeBettry();
    

     

     

     

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

    댓글

Designed by Tistory.