본문 바로가기
개발/JAVA

자바 객체지향 (11) - InnerClass

by chansungs 2020. 6. 14.
728x90
반응형

InnerClass

package inner;

// 다양한 형태의 클래스 선언
// 1. 일반적인 클래스의 선언
// - 파일 내부에 class 키워드를 사용한 클래스의 선언
// 2. 무명(익명)클래스
// - 이름이 없는 클래스
// 3. 중첩클래스
// - 클래스 내부에 새로운 클래스가 선언된 형태

// 기능의 스펙(메소드의 원형)을 정의해놓은 인터페이스의 선언
interface Inter44 {
	public abstract int sum(int n1, int n2);
	public abstract int minus(int n1, int n2);
}
// 인터페이스를 구현하고 있는 클래스의 선언
class Sub44 implements Inter44 {
	public int sum(int n1, int n2) {		
		return n1 + n2;
	}
	public int minus(int n1, int n2) {
		return n1 - n2;
	}
}
public class Class_44_InnerClass {
	public static void main(String[] args) {
		// 부모 인터페이스의 레퍼런스 변수가 자식 클래스의 객체를 참조하는 코드
		Inter44 obj = new Sub44();
		// 부모 인터페이스의 레퍼런스 변수를 사용하여
		// 자식클래스에서 오버라이딩된 메소드를 호출하는 다형성 코드
		System.out.println(obj.sum(17, 34));
		System.out.println(obj.minus(57, 19));
		
		// 무명(익명)클래스를 사용한 인터페이스의 객체 생성
		// - 추상클래스/인터페이스는 객체를 생성할 수 없습니다.
		// - 추상 메소드의 포함 가능성
		// - 추상클래스/인터페이스의 객체를 생성할 때, 메소드 오버라이딩을
		//   적용하는 방식
		// - new 추상클래스/인터페이스() { 메소드 오버라이딩 코드 }
		Inter44 instance = new Inter44() {
			public int sum(int n1, int n2) {		
				return n1 * 2 + n2 * 2;
			}
			public int minus(int n1, int n2) {
				return n1 * 2 - n2 * 2;
			}
		};
		System.out.println(instance.sum(17, 34));
		System.out.println(instance.minus(57, 19));
		
		// 익명(무명) 클래스
		// 객체를 생성하면서 오버라이딩을 하는 클래스
		// 일반클래스, 추상클래스, 인터페이스 모두에 적용이 가능합니다.
		// 인터페이스나 추상클래스 타입의 객체를 생성하면서
		// 추상 메소드를 오버라이딩 할 수 있습니다.
		// 간단한 로직의 메소드 오버라이딩 이라면
		// 클래스를 새롭게 만드는 것에 비해 코드 작성의 
		// 효율을 높일 수 있습니다.
		Inter44 interObj = new Inter44() {
			// 익명 클래스는 내부에 새로운 멤버 필드를 추가할 수 있습니다.
			int i;
			int j;
			int r;			
			// 익명 클래스는 내부에 새로운 멤버 메소드를 추가할 수 있습니다.
			public void display() {
				System.out.println("익명클래스의 새롭게 추가된 메소드입니다.");
			}
			// 추상메소드 오버라이딩
			public int sum(int n1, int n2) {
				display();
				return n1 * 2 + n2 * 2;
			}
			public int minus(int n1, int n2) {
				display();
				return n1 * 2 - n2 * 2;
			}
		};
		System.out.println(interObj.sum(17, 34));
		System.out.println(interObj.minus(57, 19));
		
		// 익명(무명) 클래스를 작성하면서 새롭게 추가한 필드/메소드는 
		// 외부에서 사용할 수 없습니다.
		// 내부에서만 사용가능!!!
		//System.out.println(interObj.i);
		//System.out.println(interObj.j);
		//System.out.println(interObj.r);
		//interObj.display();
	}
}


package inner;

import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;

// 일반적인 이벤트 처리용 클래스를 외부에 별도로 선언하는 경우
// 윈도우 상의 각 멤버를 제어할 수 없습니다.
// - 별도의 클래스로 구분되어 작성되었기 때문에
// - private 멤버이기 때문에
class WindowsAppMouseHanddler extends MouseAdapter {	
	public void mouseClicked(MouseEvent e) {
		System.out.println("화면의 버튼이 클릭되었습니다.");
	}
}

class WindowsApp extends JFrame {
	private JTextField tf = new JTextField();
	private JButton btn = new JButton("클릭하세요~!");
	private int count = 0;
	public WindowsApp() {
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setTitle("익명 클래스의 활용 예제");
		
		this.add(this.tf, BorderLayout.CENTER);
		this.add(this.btn, BorderLayout.SOUTH);
		
		// 윈도우 어플리케이션의 이벤트 처리를 외부의 별도 클래스로 처리하는 경우
		// 윈도우 각 구성요소에 접근할 수 없습니다.
		// this.btn.addMouseListener(new WindowsAppMouseHanddler());
		
		// 익명/중첩 클래스를 사용하여 이벤트를 처리하는 경우
		// 외부 클래스의 모든 요소에 접근할 수 있으므로
		// 아래와 같이 윈도우 구성요소를 수정하는 코드를 작성할 수 있습니다.
		// (private 멤버에도 자유롭게 접근이 가능합니다)
		this.btn.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				System.out.println("화면의 버튼이 클릭되었습니다.");
				// 익명클래스/내부클래스를 사용하는 경우
				// 외부에 위치한 클래스의 모든 멤버에 자유롭게
				// 접근할 수 있습니다.
				tf.setText("화면의 버튼이 클릭되었습니다 - " + ++count);
			}
		});
		
		this.setSize(550, 300);
		this.setVisible(true);
	}
	
}

public class Class_45_InnerClass_EX {
	public static void main(String[] args) {
		new WindowsApp(); 
	}
}

package inner;

// 중첩클래스
// - 클래스 내부에 또 다른 클래스를 정의하는 것

// 독립된 클래스들간에는 private 멤버에 접근할 수 없습니다.
// 하지만 중첩되어 선언된 내부 클래스의 경우에는 외부의 클래스가 가진
// 모든 멤버에 자유롭게 접근할 수 있습니다.

// 외부 클래스 Outter
class Outter {
	private int number;
	public Outter(int number, String name) {
		this.number = number;
		Inner inner = new Inner(name);
		inner.display();
	}
	
	// 내부 클래스 Inner
	class Inner {
		private String name;
		public Inner(String name) {
			this.name = name;
		}
		public void display() {
			// 중첩된 클래스는 외부 클래스의 멤버에 자유롭게 접근할 수 있습니다.
			// 아래의 number 변수는 외부 클래스의 private 멤버입니다.
			System.out.printf("%s : %d\n", this.name, number);
		}
	}
}

public class Class_46_InnerClass {
	public static void main(String[] args) {
		Outter out = new Outter(117, "Hello");
	}
}







 

package inner;

import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;

class WindowsAppInner extends JFrame {
	private JTextField tf = new JTextField();
	private JButton btn = new JButton("클릭하세요~!");
	private int count = 0;
	
	// 내부 클래스를 활용한 마우스 이벤트 처리 클래스
	class MouseEventHanddler extends MouseAdapter {
		public void mouseClicked(MouseEvent e) {
			System.out.println("화면의 버튼이 클릭되었습니다.");	
			// 내부 클래스에서 외부 클래스의 모든 멤버에 접근할 수 있습니다.
			tf.setText("화면의 버튼이 클릭되었습니다 - " + ++count);
		}
	}
	public WindowsAppInner() {
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setTitle("익명 클래스의 활용 예제");
		this.add(this.tf, BorderLayout.CENTER);
		this.add(this.btn, BorderLayout.SOUTH);
		
		// 내부 클래스의 객체를 생성하여 마우스 이벤트를 처리
		this.btn.addMouseListener(new MouseEventHanddler());	
		
		this.setSize(550, 300);
		this.setVisible(true);
	}
	
}

public class Class_47_InnerClass_EX {
	public static void main(String[] args) {
		new WindowsAppInner(); 
	}
}

 

728x90
반응형