[그린컴퓨터] Server/JAVA(객체 지향 프로그래밍)

인터페이스 요소 살펴보기 { 인터페이스 상수, 디폴트 메서드와 정적 메서드, 디폴트 메서드, private 메서드 }

Ben의 프로그램 2023. 6. 4. 21:25
728x90

인터페이스 상수

  •  인터페이스는 추상 메서드로 이루어지므로 인스턴스를 생성할 수 없으며 멤버 변수도 사용할 수 없습니다. 
  • 인터페이스에 다음과 같이 변수를 선언해도 오류가 나지 않습니다.
double PI = 3.14;
int ERROR = -99999;
  • 위와 같이 하여도 오류가 발생하지 않는 이유는 컴파일러가 자동으로 상수로 변환해주기 때문입니다.
  • 컴파일러는 public static final double PI =- 3.14; 로 선언합니다. 

디폴트 메서드와 정적 메서드

  • 자바 7까지는 인터페이스에서 추상 메서드와 상수, 이 두 가지 요소만 선언해서 사용할 수 있었습니다. 
  • 그런데, 이 추상 메서드와 상수 두 가지만 있는 인터페이스는 다음과 같은 불편한 사항들이 있었습니다. 
  • 1. 한 인터페이스를 구현한 여러 클래스에서 공통으로 갖는 메서드가 있을 수 있는데, 기존 인터페이스에서는 추상 메서드를 가질 수밖에 없기 때문에 공통으로 갖는 메서드를 만들 수가 없습니다. 
  • 자바 8부터는 이런 부분에서 인터페이스 활용성을 높이기 위해 디폴트 메서드정적 메서드 기능을 제공합니다.
  • 디폴트 메서드는 인터페이스에서 구현 코드까지 작성한 메서드입니다. 
  • 인터페이스를 구현한 클래스에 기본적으로 제공할 메서드인 것이죠. 
  • 정적 메서드는 인스턴스 생성과 상관없이 사용할 수 있는 메서드입니다. 
  • 하지만 디폴트 메서드나 정적 메서드를 추가했다고 해서 인터페이스가 인스턴스를 생성할 수 있는 것은 아닙니다. 
  • 그러면 인터페이스에 구현하는 디폴트 메서드와 정적 메서드가 무엇인지, 어떻게 호출하고 사용하는지 자세히 살펴보겠습니다. 

디폴트 메서드

  • 디폴트 메서드란 말 그대로 기본으로 제공되는 메서드입니다. 
  • 디폴트 메서드는 인터페이스에서 구현하지만, 이후 인터페이스를 구현한 클래스가 생성되면 그 클래스에서 사용할 기본 기능입니다. 
  • 디폴트 메서드를 선언할 때는 default 예약어를 사용합니다. 
  • 그러면 예를 통해서 디폴트 메서드 기능을 더 자세하게 알아봅시다. 
ublic interface Calc {
	double PI = 3.14;  // public static final 이 생략되어 있습니다. 인터페이스에서 선언한 변수는 컴파일 과정에서 자동으로 상수로 변환됨
	int ERROR = -99999;
	
	int add(int num1, int num2);  // public abstract 이 생략되어 있다. 인터페이스에서 선언한 메서드는 컴파일 과정에서 자동으로 추상 메서드로 변환됨
	int substract(int num1, int num2);
	int times(int num1, int num2);
	int divide(int num1, int num2);
	
	default void description() {
		System.out.println("정수 계산기를 구현합니다.");
	}
}
  • 디폴트 메서드는 일반 메서드완 똑같이 구현하면 되고, 메서드 자료형 앞에 default 예약어만 써 주면 됩니다. 
  • 새로 구현한 description( ) 디폴트 메서드를 사용하려면 다음 코드와 같이 인터페이스를 구현한 클래스의 인스턴스를 만들어서 사용해야합니다. 
public class CalculatorTest {

	public static void main(String[] args) {
		int num1 = 10;
		int num2 = 5;
		
		CompleteCalc calc = new CompleteCalc();
		System.out.println(calc.add(num1, num2));
		System.out.println(calc.substract(num1, num2));
		System.out.println(calc.times(num1, num2));
		System.out.println(calc.divide(num1, num2));
		calc.showInfo();
		calc.description();
	}

}
  • 디폴트 메서드는 인터페이스에 이미 구현되어 있으므로 인터페이스를 구현한 추상 클래스 Calculator 나 추상 클래스를 상속받은 CompleteCalc 클래스에서 코드를 구현할 필요가 없습니다. 

디폴트 메서드 재정의하기

  • 만약 이미 인터페이스에 구현되어 있는 디폴트 메서드가 새로 생성한 클래스에서 원하는 기능과 맞지 않는다면, 하위 클래스에서 디폴트 메서드를 재정의할 수 있습니다.
  • 디폴트 메서드의 재정의는 인터페이스를 구현한 클래스나 구현한 클래스를 상속받은 클래스에서도 재정의 가능합니다. 
  • 재정의 하는 방법은 기존 메서드의 재정의와 완벽히 동일합니다. 

정적 메서드

  • 정적 메서드는 static 예약어를 사용하여 선언하며 클래스 생성과 무관하게 사용할 수 있습니다.
  • 정적 메서드를 사용할 때는 당연스럽게 인터페이스 이름으로 직접 참조하여 사용합니다. (기존 클래스와 같음)
public interface Calc {
	double PI = 3.14;  // public static final 이 생략되어 있습니다. 인터페이스에서 선언한 변수는 컴파일 과정에서 자동으로 상수로 변환됨
	int ERROR = -99999;
	
	int add(int num1, int num2);  // public abstract 이 생략되어 있다. 인터페이스에서 선언한 메서드는 컴파일 과정에서 자동으로 추상 메서드로 변환됨
	int substract(int num1, int num2);
	int times(int num1, int num2);
	int divide(int num1, int num2);
	
	default void description() {
		System.out.println("정수 계산기를 구현합니다.");
	}
	
	static int total(int[] arr) {
		int total = 0;
		
		for (int i : arr) {
			total += i;
		}
		return total;
	}
}
  • 사용할 때는 인터페이스 이름으로 직접 참조하여 사용합니다. 

private 메서드

  • 자바 9 부터는 인터페이스에 private 메서드를 구현할 수 있습니다.
  • private 메서드는 인터페이스를 구현한 클래스에서 사용하거나 재사용할 수 없습니다. 
  • 따라서 기존에 구현된 코드를 변경하지 않고 인터페이스를 구현한 클래스에서 공통으로 사용하는 경우에 private 메서드로 구현하면 코드 재사용성을 높일 수 있습니다. 
  • 또한 클라이언트 프로그램에 제공할 기본 기능을 private 메서드로 구현하기도 합니다. 
  • private 메서드는 코드를 모두 구현해야 하므로 추상 메서드에 private 예약어를 사용할 수는 없지만, static 예약어는 함께 사용할 수 있습니다. 
  • private static 메서드정적 메서드처럼 호출하여 사용니다.
  • 그러면 Calc 인터페이스에 private 메서드와 private static 메서드를 구현하고 이를 디폴트 메서드와 정적 메서드에서 호출하여 사용해보겠습니다. 
public interface Calc {
	double PI = 3.14;  // public static final 이 생략되어 있습니다. 인터페이스에서 선언한 변수는 컴파일 과정에서 자동으로 상수로 변환됨
	int ERROR = -99999;
	
	int add(int num1, int num2);  // public abstract 이 생략되어 있다. 인터페이스에서 선언한 메서드는 컴파일 과정에서 자동으로 추상 메서드로 변환됨
	int substract(int num1, int num2);
	int times(int num1, int num2);
	int divide(int num1, int num2);
	
	default void description() {
		System.out.println("정수 계산기를 구현합니다.");
		myMethod(); // 디폴트 메서드에서 private 메서드 호출
	}
	
	static int total(int[] arr) {
		int total = 0;
		
		for (int i : arr) {
			total += i;
		}
		myStaticMethod(); // 정적 메서드에서 private static 메서드 호출
		return total;
	}
	
	private void myMethod() { // private 메서드
		System.out.println("private 메서드입니다.");
	}
	
	private static void myStaticMethod() {  // private static 메서드
		System.out.println("private static 메서드입니다.");
	}
}

 

public class CalculatorTest {

	public static void main(String[] args) {
		int num1 = 10;
		int num2 = 5;
		
		CompleteCalc calc = new CompleteCalc();
		System.out.println(calc.add(num1, num2));
		System.out.println(calc.substract(num1, num2));
		System.out.println(calc.times(num1, num2));
		System.out.println(calc.divide(num1, num2));
		calc.showInfo();
		calc.description();  // 디폴트 메서드 + 디폴트 메서드에 포함된 private 메서드 실행됨
		int[] arr = {1, 2, 3, 4, 5};
		Calc.total(arr);  // default(정적, static) 메서드에서 private static 실행
		
	}

}

 

출력값