Java 파트8-1. 인터페이스

1. 인터페이스


  • 인터페이스란 객체의 사용 방법을 정의한 타입
  • 인터페이스를 통해 다양한 객체를 동일한 사용 방법으로 이용할 수 있다.
  • 인터페이스를 이용해서 다형성을 구현할 수 있다.
  • 개발 코드는 인터페이스를 통해 객체와 서로 통신한다.
  • 인터페이스의 메소드를 호출하면 객체 메소드가 호출된다.
  • 개발 코드를 수정하지 않으면서 객체 교환이 가능하다.

쉽게 생각하면 인터페이스는 객체를 사용하기 위한 메뉴얼이라고 생각하면 된다. 메뉴얼(인터페이스)에는 불변의 상수들과 추상 메소드가 있다. 추상 메소드는 객체마다 사용방법이 다를 것이므로 당연히 메소드 선언부만 있고 구현 클래스에서 재정의를 해줘야 한다. 최종적으로는 메인 실행 클래스에서 ‘인터페이스명 변수명 = new 구현클래스명()’ 으로 사용하며, 이제 변수명. 으로 인터페이스의 불변의 상수들과 구현 클래스의 메소드, 필드들을 사용할 수 있게 된다.

그림1


2. 인터페이스 선언


  • .java 형태로 소스 파일로 작성 및 컴파일러를 통해 .class형태로 컴파일된다.
  • 클래스와 물리적 파일 형태는 같으나 소스 작성 내용이 다르다.
  • 인터페이스는 객체 사용 설명서이기 때문에 객체를 만들 목적으로 작성하지 않는다. 따라서 인터페이스는 생성자를 가질 수 없다.
interface 인터페이스이름 {...}

interface 인터페이스이름{
    // 상수, 값 수정 불가능
    타입 상수이름 = ;
    // 추상 메소드
    타입 메소드이름(매개변수,..);
}


특징

  • 인터페이스의 접근 제한자는 public이 기본, abstract도 기본으로 생략해도 된다.
  • 인터페이스 상수는 static final이 기본값이다.


3. 상수 필드 선언


  • 인터페이스에서는 데이터를 저장할 인스턴스 혹은 정적 필드 선언 불가
  • 상수 필드만 선언 가능
  • 상수 이름은 대문자로 작성하되 서로 다른 단어로 구성되어 있을 경우 언더바로 연결
타입 상수이름 = ;

public interface RemoteControl{
    public int MAX_VOLUME = 10;
    public int MIN_VOLUME = 0;
}


4. 추상 메소드 선언


  • 인터페이스를 통해 호출된 메소드는 최종적으로 객체에서 실행
  • 인터페이스의 메소드는 실행 블록이 필요 없는 추상 메소드로 선언

그림2


5. 구현 클래스


  • 인터페이스에서 정의된 추상 메소드를 재정의해서 실행내용을 가지고 있는 클래스
  • 클래스 선언부에 implements 키워드를 추가하고 인터페이스 이름 명시
// 구현클래스는 인터페이스에 있는 내용을 구현하고 있다는 뜻
// 구현클래스로부터 객체를 만들면 인터페이스로 사용할 수 있다
public class 구현클래스이름 implements 인터페이스이름{
    // 인터페이스에 선언된 추상 메소드의 실체 메소드 선언
}

// 예시
public class Television implements RemoteControl{
    // 인터페이스에 선언되어 있는 추상메소드를 실체 메소드로 재정의
    public void trunOn{
        System.out.println("TV 켜기")
    }

    public void trunOff{
        System.out.println("TV 끄기")
    }
}


6. 인터페이스 구현


인터페이스 변수;
변수 = 구현 객체;

한번에 처리
인터페이스 변수 = 구현 객체;

그림3

//예시

// 인터페이스 파일
package sec07.exam01.pack5;

public interface RemoteControl {
	int MAX_VOLUME = 10;
	int MIN_VOLUME = 0;
	
	void turnOn();
	void turnOff();
	void setVolume(int volume);
}

// 구현 클래스
package sec07.exam01.pack5;

public class Audio implements RemoteControl{// 재정의하지않으면 오류
	private int volume;
	
	@Override
	public void turnOn() {
		System.out.println("Audio 켜기");
		
	}

	@Override
	public void turnOff() {
		System.out.println("Audio 끄기");
		
	}

	@Override
	public void setVolume(int volume) {
		if (volume>RemoteControl.MAX_VOLUME) {
			this.volume = RemoteControl.MAX_VOLUME;
		} else if (volume<RemoteControl.MIN_VOLUME){
			this.volume = RemoteControl.MIN_VOLUME;
		} else {
			this.volume = volume;
		}
		System.out.printf("현재 Audio 볼륨: %d\n",this.volume);		
		
	} 	
}

// 구현 클래스
package sec07.exam01.pack5;

public class Television implements RemoteControl{// 재정의하지않으면 오류
	private int volume;
	
	@Override
	public void turnOn() {
		System.out.println("TV 켜기");
		
	}

	@Override
	public void turnOff() {
		System.out.println("TV 끄기");
		
	}

	@Override
	public void setVolume(int volume) {
		if (volume>RemoteControl.MAX_VOLUME) {
			this.volume = RemoteControl.MAX_VOLUME;
		} else if (volume<RemoteControl.MIN_VOLUME){
			this.volume = RemoteControl.MIN_VOLUME;
		} else {
			this.volume = volume;
		}
		System.out.printf("현재 TV 볼륨: %d\n",this.volume);		
		
	} 
	
	
}

// 실행 메인 클래스
package sec07.exam01.pack5;

public class RemoteControlExam {

	public static void main(String[] args) {
		RemoteControl rc = new Television();
		
		rc.turnOn();
		rc.setVolume(5);
		rc.turnOff();
		
		rc = new Audio();
		rc.turnOn();
		rc.setVolume(5);
		rc.turnOff();

	}

}

구현 클래스를 작성할 때 인터페이스의 추상메소드를 일일이 복붙해서 재정의하기 불편한데 이때 선언부를 잘 확인하면 매우 간단히 해결할 수 있다. 위 코드를 예시로 하면 구현 클래스에서 재정의할 때 public class Audio implements RemoteControl {} 에서 Audio에 밑줄이 그어질 것이다.(재정의를 안했기 때문) 밑줄에 마우스를 가져다 대서 Add unimplemented methos를 클릭하면 자동으로 재정의가 필요한 추상 메소드들을 가져와 준다.

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


  • 상속은 하나의 부모 클래스만 가질 수 있었지만, 인터페이스는 하나의 객체에 다수의 인터페이스를 사용 가능
  • 각각의 인터페이스는 자신의 메소드만 사용 가능 -> A,B의 인터페이스가 사용될 때 A는 B의 메소드를 사용할 수 없다.

그림4

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


// 예시

// 인터페이스 1
package sec07.exam01.pack5;

public interface RemoteControl {
	int MAX_VOLUME = 10;
	int MIN_VOLUME = 0;
	
	void turnOn();
	void turnOff();
	void setVolume(int volume);
	void search(String url);
}

// 인터페이스 2
package sec07.exam01.pack5;

public interface Searchable {
	void search(String url);
}


// 구현 클래스 
package sec07.exam01.pack5;

// SmartTelevision이 인터페이스 2개로 사용 가능하게 만들어야하므로
// 두 개의 추상 메소드를 모두 실체 메소드로 선언해야 한다.
public class SmartTelevision implements RemoteControl, Searchable{
	private int volume;
	
	@Override
	public void turnOn() {
		System.out.println("TV 켜기");		
	}

	@Override
	public void turnOff() {
		System.out.println("TV 끄기");		
	}

	@Override
	public void setVolume(int volume) {
		if (volume>RemoteControl.MAX_VOLUME) {
			this.volume = RemoteControl.MAX_VOLUME;
		} else if (volume<RemoteControl.MIN_VOLUME){
			this.volume = RemoteControl.MIN_VOLUME;
		} else {
			this.volume = volume;
		}
		System.out.printf("현재 TV 볼륨: %d\n",this.volume);		
		
	}
	
	@Override
	public void search(String url) {
		System.out.printf("%s를 검색\n", url);		
	} 	
}

// 실행 메인 클래스
package sec07.exam01.pack5;

public class SmartTelevisionExam {

	public static void main(String[] args) {
		SmartTelevision tv = new SmartTelevision();
		
		RemoteControl rc = tv;
        // 각자에 해당하는 메소드만 사용 가능		
		rc.turnOn();
		rc.setVolume(5);
		rc.turnOff();
		
        
		Searchable searchable = tv;
        // 각자에 해당하는 메소드만 사용 가능
		searchable.search("www.google.com");		
	
	}

}


8. 인터페이스의 사용


인터페이스는 필드, 매개 변수, 로컬 변수의 타입으로 선언가능

그림5

매개 변수 타입으로 인터페이스가 사용될 때, 인터페이스는 객체를 생성할 수 없기 때문에 인터페이스로 사용할 수 있는 구현 객체를 대입 하면 된다.

// 예시

// 인터페이스 사용 클래스
package sec07.exam01.pack5;

public class MyClass {
	// SmartTelevision이 RemoteControl 인터페이스의 구현 클래스로 정의된 상황
	
	// Field
	// 필드로 인터페이스 사용	
	RemoteControl rc = new SmartTelevision();
	
	// Constructor
	MyClass(){
		
	}
	
	// 매개인자로 인터페이스 사용
	// 인터페이스는 객체 생성이 불가능하므로 구현 클래스의 객체가 인자로 대입 가능
	MyClass(RemoteControl rc){
		this.rc = rc;
		rc.turnOn();
	}
	
	// Method
	void methodA() {
		// 로컬 변수로 인터페이스 사용
		RemoteControl rc = new Audio();
		rc.turnOn();
	}
	void methodB(RemoteControl rc) {
		rc.turnOn();
	}
	
}

// 실행 메인 클래스
package sec07.exam01.pack5;

public class MyClassExam {
	public static void main(String[] args) {
		
		System.out.println("--------------------");
		
		MyClass myClass1 = new MyClass();
		// rc는 SmartTelevision의 객체이므로 SmartTelevision의 메소드 사용 가능
		myClass1.rc.turnOn();
		myClass1.rc.setVolume(5);
		
		
		System.out.println("--------------------");
		
		// Audio는 RemoteControl 인터페이스의 구현 클래스 객체이므로 매개인자로 사용 가능
		MyClass myClass2 = new Myclass(new Audio());
		
		System.out.println("--------------------");
		
		MyClass myClass3 = new MyClass();
		myClass3.methodA();
		
		System.out.println("--------------------");
		
		MyClass myClass4 = new MyClass();
		// SmartTelevision은 RemoteControl 인터페이스의 구현 클래스 객체이므로 매개인자로 사용 가능
		myClass3.methodB(new SmartTelevision());
	}
}


9. 정리하기


  • 인터페이스 : 객체의 사용 방법을 정의한 타입
  • 상수 필드 : 인터페이스의 필드는 기본적으로 public static final 특성을 가짐
  • 추상 메소드 : 인터페이스의 메소드는 public abstract가 생략되고 메소드 선언부만 있는 추상 메소드
  • implements : 구현 클래스에는 어떤 인터페이스로 사용 가능한지 기술하기 위해 사용
  • 인터페이스 사용 : 클래스 선언 시 필드, 매개인자, 로컬 변수로 선언 가능, 객체 생성이 불가능하므로 구현 클래스 객체를 대입

cf) 추상 클래스 vs 인터페이스

비교목적구성
추상 클래스추상 클래스는 서브 클래스에서 필요로 하는 대부분의 기능을 구현하여 만들어 놓고 서브 클래스가 상속받아 활용할 수 있도록 하되, 서브 클래스에서 구현할 수밖에 없는 기능만을 추상 메서드로 선언하여 서브 클래스에서 구현하도록 하는 목적(다형성)+ 추상 메서드와 일반 메서드를 모두 포함
+ 상수, 변수 필드도 포함
인터페이스인터페이스는 객체의 기능을 모두 공개한 표준화 문서와 같은 것으로, 개발자에게 인터페이스를 상속받는 클래스의 목적에 따라 인터페이스의 모든 추상 메서드를 만들도록 하는 목적(다형성)+ 변수 필드(멤버 변수)는 포함하지 않음
+ 상수, 추상 메서드, 일반 메서드, default 메서드, static 메서드 모두 포함
+ protected 접근 지정 선언 불가
+ 다중 상속 지원



본 포스팅은 ‘혼자 공부하는 자바’를 읽고 공부한 내용을 바탕으로 작성하였습니다.


© 2021. By Backtony