본문 바로가기
👨‍🏫Study/JAVA

[JAVA] 08 - 1 인터페이스

by 코푸는 개발자 2022. 3. 21.
728x90
인터페이스란 ?

 

- 기능 사용을 위한 규약

- 객체의 사용 방법을 정의한 타입

- 다양한 객체를 동일한 방법으로 이용할 수 있게 해줌

- 개발 코드에서 인터페이스의 메소드를 호출하면 이제 인터페이스가 객체의 메소드를 호출시킴

- 개발 코드를 수정하지 않고 객체를 변경할 수 있게 하여 개발 코드 측면에서 실행 내용과 리턴 값을 다양화할 수 있다.

 

인터페이스 선언

 

1. 특징 

- 클래스와 규칙이 동일함 (대문자로 시작)

- 상수 필드와 추상 메소드만을 멤버로 가진다. ( 객체를 생성할 수 없기 때문에 생성자는 가질 수 없음)

- 인터페이스는 객체 사용 방법만 정의한 것이므로 인스턴스나 정적 필드를 선언할 수 없다. (상수 필드는 고정된 값이므로 선언이 가능)

- 최종 실행은 객체에서 실행되므로 인터페이스에서 메소드의 실행 코드를 입력할 필요가 없다. 

- 따라서 인터페이스에서는 추상 메소드를 선언해준다.

 

2. 형태 

public interface RemoteControl { // 인터페이스 생성
	// 상수
	public static final int MAX_VALUE = 10; // public static final은 생략 가능, 자동으로 붙게됨
	
	// 추상 메소드
	public abstract void turnOn(); // public abstract 생략 가능, 자동으로 붙게됨
}

 

 

인터페이스 구현

 

- 위에서 다룬 예제와 같이 RemoteControl 은 인터페이스고 이제 Television과 Audio가 구현 클래스가 된다.

 

- 구현 클래스 : 구현 객체를 생성하는 클래스로, 인터페이스에서 정의한 추상메소드를 구현 클래스에서 오버라이딩한 실체 메소드를 가지고 있어야 한다. 

- 구현 객체 : 구현 클래스로 만들어진 객체를 말한다.

 

 

구현 클래스

 

- 특징 : 보통 클래스와 동일하지만 인터페이 타입으로 사용이 가능함을 알리기 위해 implements 키워드 사용한다.

- 특징 : 인터페이스에 선언된 추상 메소드의 실체 메소드를 선언해야함

 

- 형태 :

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

 

 

인터페이스 구현 예제 

 

<인터페이스>

public interface RemoteControl { // 인터페이스 생성
	// 상수
	public static final int MAX_VALUE = 10; // public static final은 생략 가능, 자동으로 붙게됨
	public static final int MIN_VALUE = 0;
	
	// 추상 메소드 -> 기본적으로 전부 public 접근 제한자를 가짐
	public abstract void turnOn(); // public abstract 생략 가능, 자동으로 붙게됨
	public abstract void turnOff();
	public abstract void setVolume(int volume);	
}

 

<구현 클래스 1> 

class Television implements RemoteControl { // 인터페이스 사용이 가능하게 됨
	// 필드
	private int volume;
	
    // RemoteControl 인터페이스에 있는 추상 메소드 세개에 대한 실체 메소드를 모두 작성해주어야함
    // 인터페이스의 추상 메소드가 모두 public 접근 제한을 가지므로 더 낮은 접근 제한으로 실체 메소드 작성 불가
    
	// turnOn() 메소드의 실체 메소드
	public void turnOn() {
		System.out.println("TV를 켭니다.");
	}
	
	// turnOff() 메소드의 실체 메소드
	public  void turnOff() {
		System.out.println("TV를 끕니다.");
	}
	
	// setVolume() 메소드의 실체 메소드
	public void setVolume(int volume) {
		if(volume > RemoteControl.MAX_VALUE) { // 인터페이스 상수를 이용해서 volume 필드의 값을 제한
			this.volume = RemoteControl.MAX_VALUE; // 최대값을 넘으면 값을 최대값으로 지정(최대값을 못넘도록 해줌)
		} else if(volume < RemoteControl.MIN_VALUE) {
			this.volume = RemoteControl.MIN_VALUE;
		} else {
			this.volume = volume;
		}
		System.out.println("현재 TV 볼륨 : " + this.volume);
	}
}

 

<구현 클래스 2> 

class Audio implements RemoteControl {
	// 필드
	private int volume; 
	
	// turnOn() 메소드의 실체 메소드
	public void turnOn() {
		System.out.println("Audio를 켭니다.");
	}
	
	// turnOff() 메소드의 실체 메소드
	public void turnOff() {
		System.out.println("Audio를 끕니다.");
	}
	
	// setVolume() 메소드의 실체 메소드
	public void setVolume(int volume) {
		if(volume > RemoteControl.MAX_VALUE) {
			this.volume = RemoteControl.MAX_VALUE;
		} else if(volume < RemoteControl.MIN_VALUE) {
			this.volume = RemoteControl.MIN_VALUE;
		} else {
			this.volume = volume;
		}
		System.out.println("현재 Audio 볼륨 : " + this.volume);
	}
}

 

<인터페이스 객체에 구현 객체 대입>

- Television tv = new Television();  <- 이 방법은 인터페이스를 사용하여 객체를 만든 것이 아님

- 인터페이스 변수를 먼저 선언하고 구현 객체를 대입해주어야함

-  인터페이스 변수는 참조 타입이므로 구현 객체를 대입할 때 구현 객체의 번지가 저장됨

public class RemoteControlExample {
	public static void main(String[] args) {
		RemoteControl rc;
		rc = new Television();
		rc = new Audio();
	}
}

 

 

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

 

- 여러 인터페이스로부터 구현 클래스를 작성하기 위해선 모든 인터페이스에 선언된 추상 메소드의 실체 메소드를 선언

- 형태

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

 

다중 인터페이스 구현 예제 

 

<인터페이스>

interface Searchable {
	// 추상 메소드
	void search(String Url);
}

 

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

class SmartTelevision implements RemoteControl, Searchable {
	// 필드
	private int volume;
	private String name;
	
	// 생성자
	public SmartTelevision(String name) {
		this.name = name;
	}
	
	// 실체 메소드
	@Override
	public void search(String url) {
		System.out.println(url + "을 검색합니다.");
	}
	
	@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_VALUE) {
			this.volume = RemoteControl.MAX_VALUE;
		} else if(volume < RemoteControl.MIN_VALUE) {
			this.volume = RemoteControl.MIN_VALUE;
		} else {
			this.volume = volume;
		}
		System.out.println("현재 TV 볼륨 : " + this.volume);
	}
}

 

<인터페이스 변수에 구현 객체 대입>

public class SmartTelevisionExample {
	public static void main(String[] args) {
		SmartTelevision stv = new SmartTelevision("SAMSUNG smart TV"); // 구현 객체 생성
		// 자동 형변환 (RemoteControl <- SmartTelevision)
		// RemoteControl 기능만 사용 가능
		RemoteControl rc = stv; // 인터페이스 변수에 객체 대입
		rc.turnOn();
		
		//자동 형변환 (Searchable <- SmartTelevision)
		// Searchable 기능만 사용 가능
		Searchable sc = stv;
		sc.search("www.google.com");
		// sc.turnOn(); 사용 못함
	}
}

 

<출력 결과>

TV를 켭니다.
www.google.com을 검색합니다.

 

 

인터페이스 사용 과정 구조화

 

인터페이스 사용 과정

 

- 인터페이스는 개발 코드(MyClass)와 구현 객체(Television, Audio) 사이에서 접점 역할을 담당

- 개발 코드에서 인터페이스(RemoteControl)의 추상메소드(turnOn(), turnOff()) 호출

- 호출된 인터페이스는 구현 객체의 재정의 메소드인 실체 메소드(turnOn(), turnOff())를 호출함

 

 

인터페이스 사용

 

- 구현 객체가 인터페이스 변수에 대입되므로 이제 인터페이스로 구현 객체를 사용할 수 있다.

 

- 인터페이스가 쓰이는 예시

1. 필드로 사용

// 객체 코드 myClass에서 인터페이스를 필드로 선언
RemoteControl rc = new Television();

// 객체 코드 myClass 에서 선언된 필드 사용
MyClass myclass = new MyClass(); // 객체 생성
myClass.rc.turnOn(); // rc 변수에는 Television 객체의 번지가 저장되어있으므로 
myClass.rc.setVolume(5); // television의 메소드가 실행됨

 

2. 생성자의 매개변수 타입으로 사용 ( 메소드의 매개변수로도 사용 가능)

// 객체 코드 MyClass의 생성자에서 인터페이스를 매개변수로 사용
MyClass(RemoteControl rc) { // 매개변수에 인터페이스 타입이 들어감
  this.rc = rc;
  rc.turnOn(); // 인터페이스의 메소드 호출
  rc.setVolume(5);
}

// 객체를 생성할 때 구현 객체를 받으면 구현 클래스의 실체 메소드가 실행됨
MyClass myClass = new MyClass(new Audio()); // Audio의 메소드들이 실행됨

 

3. 메소드 내부에서 로컬 변수로 사용 (생성자의 로컬 변수로도 가능)

// 메소드 안에서 로컬 변수로 인터페이스 타입이 사용됨
void methodA() {
  RemoteControl rc = new Audio();
  rc.turnOn(); // Audio의 turnOn()이 실행됨
  rc.setVolume(5); // Audio의 setVolume(5)이 실행됨
}

 

4. 메소드의 매개변수 타입으로 사용

// 메소드의 매개변수 타입으로 사용
void methodB(RemoteControl rc) {
  rc.turnOn();
  rc.setVolume(5);
}

// 실행 클래스에서 methodB() 호출
MyClass myClass = new MyClass();
myClass.methodB(new Television());

 

인터페이스 사용 예제

 

<개발 코드> 

public class MyClass {
	// 인터페이스의 사용 예시 4가지
	
	// 1. 필드로 사용
	RemoteControl rc = new Television();
	
	// 기본 생성자
	MyClass() {
		
	}
	
	// 2. 생성자로 사용
	MyClass(RemoteControl rc) { // 매개변수에 인터페이스 타입이 들어감
		this.rc = rc;
		rc.turnOn(); // 인터페이스의 메소드 호출
		rc.setVolume(5);
	}
	
	// 3. 메소드 내에서 로컬 변수로 사용
	void methodA() {
		RemoteControl rc = new Audio();
		rc.turnOn(); // Audio의 turnOn()이 실행됨
		rc.setVolume(5); // Audio의 setVolume(5)이 실행됨
	}
	
	// 4. 메소드의 매개변수 타입으로 사용
	void methodB(RemoteControl rc) {
		rc.turnOn();
		rc.setVolume(5);
	}
}

 

<객체 코드> 

public class MyClassExample {
	public static void main(String[] args) {
		System.out.println("1)----------------");
		
		MyClass myClass1 = new MyClass();
		myClass1.rc.turnOn();
		myClass1.rc.setVolume(5);
		
		System.out.println("2)----------------");
		MyClass myclass2 = new MyClass(new Audio());
		
		System.out.println("3)----------------");
		MyClass myClass3 = new MyClass();
		myClass3.methodA();
		
		System.out.println("4)----------------");
		MyClass myClass4 = new MyClass();
		myClass4.methodB(new Television());
	}
}

 

<출력 결과> 

1)----------------
TV를 켭니다.
현재 TV 볼륨 : 5
2)----------------
Audio를 켭니다.
현재 Audio 볼륨 : 5
3)----------------
Audio를 켭니다.
현재 Audio 볼륨 : 5
4)----------------
TV를 켭니다.
현재 TV 볼륨 : 5

 

728x90

댓글