언어/Java

기초 #11. 중첩 인터페이스와 익명 객체 (+예제 1,2)

뭉지(moonz) 2020. 9. 6. 23:48
반응형

중첩 클래스를 다뤘으니 이제 중첩 인터페이스를 다루겠다.

 

중첩 인터페이스

----------------------------------------------------------------------------------------

▶클래스 내부에 선언한 인터페이스

▶주로 UI 작업을 위한 이벤트에 많이 활용된다.

▶인터페이스를 클래스 내부에 선언하는 이유?

해당 클래스와 긴밀한 관계를 맺는 구현 클래스를 만들기 위해서.

 

예제

---------------------------------------------------------------------------------------------------------------------------------

1. 내부에 중첩 인터페이스 보유한 클래스 코드

public class Button {
	OnClickListener listener;	//인터페이스타입 객체
	
	//일반 메서드. 매개변수에 new 형식으로 들어올 듯.
	void setOnClickListener(OnClickListener listener) {
		this.listener = listener;
	}
	
	void touch() {	//일반 메서드
		listener.onClick();//그 객체의 onClick() 호출
	}
	
	interface OnClickListener {	//중첩 인터페이스
		void onClick();	//추상메서드
	}
}

2. 인터페이스 지정한 클래스 2개 코드

public class MessageListener implements Button.OnClickListener {	//Button클래스 내부의 인스턴스이기 때문에 Button.OnclickListener

	@Override
	public void onClick() {
		System.out.println("메시지를 보냅니다.");
	}
}

public class CallListener implements Button.OnClickListener {	

	@Override
	public void onClick() {
		System.out.println("전화를 겁니다.");
	}
}

3. 메인 코드

public class ButtonEx {
	public static void main(String[] args) {
    	Button btn = new Button();
        
        btn.setOnClickListener(new CallListener);	//this.listener = new CallListener;
        btn.touch();	//"전화를 겁니다" 출력
        
        btn.setOnClickListener(new MessageListener);	//this.listener = new MessageListener;
        btn.touch();	//"메시지를 보냅니다" 출력
    }
}

[결과]

익명 객체

----------------------------------------------------------------------------------------

▶이름이 없는 객체

▶new와 동시에 부모클래스를 상속받아 내부에서 오버라이딩한다.

▶익명클래스 내부의 필드를 익명클래스 밖에서 사용할 수 없다.

▶익명 클래스는 언제 사용될까?

상속은 받아야하지만, 한번만 사용할 것이라서 extends 문법을 굳이 사용 안할 때

▶사용 위치

1. 필드의 초기값, 로컬변수의 초기값, 매개변수의 매개값으로 주로 대입. ->초기값 설정에 주목

2. UI 이벤트 처리 객체 / 스레드 객체를 간편하게 생성할 목적으로 주로 활용.

▶익명클래스 내부에는 생성자있을 수 없다.

▶익명객체에서 새롭게 필드와 메서드를 정의할 수 있다.

단, 익명 객체 내부에서만 사용할 수 있고, 외부에서는 익명 객체의 필드/메소드에 접근할 수 없다.

(부모 타입을 오버라이딩한 것만 사용 가능)

▶익명클래스에서는 외부의 자원 중 final 키워드 붙은 요소만을 사용할 수 있다.

▶단독 생성 불가. 클래스를 상속하거나 인터페이스를 구현해야만 생성 가능.

▶[익명 구현 객체 생성 형식]

인터페이스명 변수명 = new 인터페이스명() {
  //인터페이스에 선언된 추상 메서드 오버라이딩.
  //새로운 필드
  //새로운 메서드
};

예제

----------------------------------------------------------------------------------------

1. Person 클래스 코드

public class Person {
  void wake() {
  	System.out.println("익명 객체 구현 전 Person은 8시에 일어납니다.");
  }
}

2. Anonymous 클래스 코드

public class Anonymous {
  /*필드 초기값으로 대입*/
  Person field = new Person() {
    void work() {
      System.out.println("출근합니다.");
    }
    void wake() {
      System.out.println("field는 6시에 일어납니다.");
      work();
    }
  };
  void method1() {
    /*로컬 변수값으로 대입*/
    Person localVar = new Person() {
      void walk() {
        System.out.println("산책합니다.");
      }
      void wake() {
        System.out.println("method1()은 7시에 일어납니다.");
        walk();
      }
    };
    //로컬변수 사용
    localVar.wake();	//localVar 익명객체 안에 구현된 wake()가 호출됨.
  }
  void method2(Person person) {
    Person.wake();
  }
}

3. 메인 코드

public class AnonymousEx {
  public class static void main(String[] args) {
    Anonymous anony = new Anonymous();
    anony.field.wake();	//익명객체 필드 사용, filed 익명객체 구현 안에 wake()가 호출됨.

    anony.method1();	//익명객체 로컬변수 사용, 
    //localVar.wake() 문이 수행되어 localVar 익명객체 구현 안에 wake()가 호출됨.

    anony.method2(new Person);	
    //Person타입 객체가 생성되어 person.wake()가 호출되므로 Person클래스에 선언된 wake()가 호출됨.
    
    anony.method2(	//익명객체 매개값 사용, 이 안에 구현된 wake()가 호출됨.)
      new Person() {
        void study() {
            System.out.println("공부합니다.");
        }
        void wake() {
            System.out.println("method2()는 8시에 일어납니다.");
            study();
        }
      }
    );	
  }
}

[결과]

예제2 (로컬 변수 사용)

----------------------------------------------------------------------------------------

1. 인터페이스 Calculatable 코드

public interface Calculatable {
	public int sum();	//추상메서드
}

2. Anonymous1 클래스 코드

public class Anonymous1 {
	private int field;
	
	public void method(final int arg1, int arg2) {
		final int var1 = 0;
		int var2 = 0;
		
		field = 10;
		
		//arg1 =20;	final이니까
		//arg2 =20; 왜지?
		//var1=30;  final이니까
		//var2 =30; 왜지?
		
		Calculatable calc = new Calculatable() {
			
			@Override
			public int sum() {
				int result = field+arg1+arg2+var1+var2;
				return result;
			}
		};
		System.out.println(calc.sum());
	}
}

3. 메인 코드

public class AnonymousEx1 {
	public static void main(String[] args) {
		Anonymous1 anony = new Anonymous1();
		anony.method(0, 0);
	}
}

[결과]

반응형