Programming/Java

[Java 자바] 9. 중첩 ② 중첩 인터페이스, 익명 객체

erinh 2022. 8. 9. 20:51
반응형

9-3. 중첩 인터페이스

- 클래스 멤버로 선언된 인터페이스를 의미
- 클래스 내부에 선언함으로써 해당 클래스와 긴밀한 관계를 맺는 구현 클래스를 만들기 위해 사용
- 특히 UI프로그래밍에서 이벤트를 처리할 목적으로 자주 활용됨

//Button.java
public class Button {

  // 인터페이스 타입 필드
  OnClickListener listener;
  
  // 매개 변수의 다형성
  void setOnClickListener(OnClickListener listener) {
    this.listener = listener;
  }
  
  // 구현 객체의 onClick() 메소드 호출
  void touch() {
    listener.onClick();
  }
  
  // 중첩 인터페이스
  interface OnClickListener {
    void onClick();
  }

}

//CallListener.java
public class CallListener implements Button.OnClickListener {
  @Override
  public void onClick() {
    System.out.println("전화를 겁니다.");
  }
}

//MessageListener.java
public class MessageListener implements Button.OnClickListener {
  @Override
  public void onClick() {
    System.out.println("메시지를 보냅니다.");
  }
}

//ButtonTest.java
public class ButtonTest {
  public static void main(String[] args) {
    Button btn = new Button();
    
    btn.setOnClickListener(new CallListener());
    btn.touch();
    
    btn.setOnClickListener(new MessageListener());
    btn.touch();
  }
}

9-4. 익명 객체

- 익명객체란 이름이 없는 객체로, 클래스를 상속하거나 인터페이스를 구현해야만 생성할 수 있음

9-4-1. 익명 자식 객체 생성

- 자식 클래스가 재사용되지 않고, 오로지 특정 필드와 변수의 초기값으로만 사용할 경우라면 익명 자식 객체를 생성하여 대입
- 끝에 세미클론(;)을 반드시 붙여야 함

// 자식 객체를 사용하여 필드와 로컬 변수에 자식 객체를 대입
class Child extends Parents { }

class A {
  Parent field = new Child();
  void method() {
    Parent localVar = new Child();
  }
}


// 위의 코드를 익명 객체를 활용하여 변경하면 아래와 같이 변경 가능
// 1. 필드 선언시 초기값으로 익명 자식 객체를 생성하여 대입
class A {
  Parent field = new Parent() {
    int childField;
    void childMethod() { }
    @Override
    void parentMethod() { }
  };
}

// 2. 로컬 변수 선언시 초기값으로 익명 자식 객체를 생성하여 대입
class A {
  void method() {
    Parent localVar = new Parent() {
      int childField;
      void childMethod() { }
      @Override
      void parentMethod() { }
    };
  }
}

9-4-2. 익명 구현 객체 생성

- 인터페이스 타입으로 필드나 변수를 선언하고, 구현 객체를 초기값으로 대입하는 경우

//인터페이스 타입으로 필드 변수 선언 후, 구현 객체를 초기값으로 대입하는 경우
class TV implements RemoteControl { }

class A {
  // 1. 필드에 구현 객체를 대입
  RemoteControl field = new TV();
  
  // 2. 로컬 변수에 구현 객체를 대입
  void method() {
    RemoteControl localVar = new TV();
  }
}

//구현클래스가 재사용되지 않고, 오로지 초기값으로 사용되는 경우 익명 구현 객체를 초기값으로 대입
// 1. 필드 선언시 초기값으로 익명 구현 객체 생성 후 대입
class A {
  RemoteControl field = new RemoteControl() {
    @Override
    void turnOn() { }
  };
}

// 2. 메소드 내에서 로컬 변수를 선언할 때 초기값으로 익명 구현 객체 생성 후 대입
class A {
  RemoteControl localVar = new RemoteControl() {
    @Override
    void turnOn() { }
  };
}

// 3. 메소드의 매개변수가 인터페이스 타입일 경우,
// 메소드 호출 코드에서 익명 구현 객체를 생성하여 매개값으로 대입
class A {
  void method1(RemoteControl rc) { }
  
  void method2() {
    method1(
      new RemoteControl() {
        @Override
        void turnOn(){ }
      }
    };
  }
}

9-4-3. 익명 객체의 로컬 변수 사용

- 익명 객체 내부에서 메소드의 매개 변수나 로컬 변수를 사용할 경우, 이 변수들은 final 특성을 갖게 됨

//Calculatable.java
public interface Calculatable {
  public int sum();
}

//Anonymous.java
public class Anonymous {
  private int field;
  
  public void method(final int arg1, int arg2) {
    final int var1 = 0;
    int var2 = 0;
    
    field = 10;
    
    //arg1 = 20; (x)
    //arg2 = 20; (x)
    
    //var1 = 30; (x)
    //var2 = 30; (x)
    
    Calculatable calc = new Calculatable() {
      @Override
      public int sum() {
        int result = field + arg1 + arg2 + var1 + var2;
        return result;
      }
    };
    
    System.out.println(calc.sum());
  }
}

//AnonymousTest.java
public class AnonymousTest {
  public static void main(String[] args) {
    Anonymous anony = new Anonymous();
    anony.method(0, 0);
  }
}
반응형