2 minute read

인터페이스의 private 메서드, JAVA 9

java8 에서는 default method와 static method가 추가되었고, java9에서는 private method와 private static method가 추가되었다.

default method와 static method의 불편함 (캡슐화가 힘듬)

  • 단지 특정 기능을 처리하는 내부 method 인데, 외부로 공개되는 public method로 만들어야 하기 때문이다.
  • 인터페이스를 구현하는 다른 인터페이스 혹은 클래스가 해당 메서드에 엑세스하거나 상속하는 것을 원하지 않는경우 불편하다.
  • 코드의 중복 및 인터페이스에 대한 캡슐화를 유지하기 위해서 사용
public interface Car {
    void carMethod();
 
    default void defaultCarMethod() {
        System.out.println("Default Car Method");
 
        privateCarMethod();
        privateStaticCarMethod();
    }
 
    private void privateCarMethod() {
        System.out.println("private car method");
    }
 
    private static void privateStaticCarMethod() {
        System.out.println("private static car method");
    }
}

public class DefaultCar implements Car {
 
    @Override
    public void carMethod() {
        System.out.println("car method by DefaultCar");
    }
}

public class Main {
    public static void main(String[] args) {
        DefaultCar car = new DefaultCar();
 
        car.carMethod();
        car.defaultCarMethod();
    }
}

// output 
// car method by DefaultCar
// Default Car Method
// private car method
// private static car method

굳이 static method 까지 private를 붙여야 하나?

  • 위 코드에서 privateCarMethod(), privateStaticCarMethod() 는 완벽히 같은 기능을 한다.
  • 그렇다면 그냥 privateCarMethod(), privateCarMethod2() 이런식으로 구현해서 사용하면 캡슐화가 유지될텐데…
  • 왜? static method 까지 private 기능이 생겼나 의문이 생겼다.
  • 하나의 이유는 인터페이스 내에서도 클래스를 구현할 수 있기 때문이라고 생각한다.
  • 다른 하나의 이유는 정적 메서드와 메서드의 차이점 때문이다.

인터페이스 내의 내부클래스(Inner Class)와 중첩클래스(Nested Class)

내부 클래스는 다른 클래스 내부에 선언되는 클래스를 말하며, 인터페이스 내부에도 선언할 수 있다. 인터페이스 내부 클래스는 두 가지 유형이 있다.

  • 정적 내부 클래스 (Static Nested Class)
    • 인터페이스 내부에 선언되는 클래스이며 static 키워드를 사용하여 선언한다.
    • 외부 클래스의 인스턴스에 종속되지 않는 정적 클래스이다.
public interface MyInterface {
    void doSomething();
    static class MyStaticNestedClass {
        void doSomethingElse() {
            System.out.println("doSomethingElse() is called.");
        }
    }
}
  • 내부 클래스 (Inner Class)
    • 인터페이스 내부에 선언되는 클래스이며 static 키워드를 사용하지 않고 선언된다.
    • 외부 클래스의 인스턴스에 종속되며, 외부 클래스의 인스턴스를 생성해야 내부 클래스의 인스턴스를 생성할 수 있다.
public interface MyInterface {
    void doSomething();
    class MyInnerClass {
        void doSomethingElse() {
            System.out.println("doSomethingElse() is called.");
        }
    }
}
  • 위 코드에서 볼 수 있듯이, 내부 클래스와 정적 내부 클래스는 인터페이스 내에서 다른 클래스와 마찬가지로 정의된다.
  • 단지, 인터페이스 내에서 정의된 클래스이기 때문에 해당 인터페이스와 밀접한 관련이 있는 클래스를 정의할 때 사용한다고 한다.

정적 메서드와 메서드의 차이점

  • 정적 메서드는 클래스에 속하고 객체에 독립적이다.
  • 인스턴스 메서드는 객체에 속하고 객체에 종속적이다.

결론

public interface MyInterface {
    void doSomething();
		// 내부 클래스 구현
    class MyInnerClass {
        void doSomethingElse() {
            System.out.println("doSomethingElse() is called");
        }
        private int notStaticCalculateSum(int x, int y) {
            return x + y;
        }
    }
		// 내부 클래스2에 private static method 구현
    class MyInnerclass2 {
        private static int calculateSum(int x, int y) {
            return x + y;
        }
    }
		// default 메서드에 내부클래스2에서 구현한 static method 사용
    default void detailMethod() {
        int sum = MyInnerclass2.calculateSum(1,2);
        System.out.println("sum: " + sum);
    }
		// default 메서드에 내부클래스 1의 객체를 불러와서 사용해야함
    default void detailMethod2() {
        MyInnerClass myInnerClass = new MyInnerClass();
        int sum = myInnerClass.notStaticCalculateSum(1,2);
        System.out.println("sum: " + sum);
    }
		// default 메서드3에 static method와 method 사용	
	default void detailMethod3() {
		int x = 1;
		int y = 1;
		int sum = 0;
		sum = calculateMethod(x, y);
		sum = MyInnerclass2.calculateSum(x, y);
	}	                          
                 	     
    private int calculateMethod(int x, int y) {
        return  x + y;
    }
}
  • 위 코드처럼 MyInnerClass2 클래스에 static 메서드를 구현하여 인스턴스를 불러오지 않고 메서드를 사용할 수 있다.
  • 반면 MyInnerClass 클래스에 private 메서드를 구현한 경우 인스턴스를 불러와서 메서드를 사용해야 한다.
  • private method 와 private static method 는 주로 헬퍼 메서드(helper method)로 사용된다. 이러한 메서드는 클래스(여기서는 인터페이스) 내부에서만 사용되며, 클래스 외부에서는 사용될 필요가 없기 때문이다(캡슐화)
  • 사실 인터페이스 내 클래스 구현을 실제로 많이 사용할까 의문이 들기도 하고, 사용해본적이 없기도 하다. 잘 아시는 분이 예시를 알려주시면 좋겠다🙋‍♂️

Leave a comment