클래스(내부클래스,익명클래스)

최동민·2022년 5월 23일
0

JAVA

목록 보기
6/13

내부 클래스(inner class)

클래스 내부에 클래스를 선언하여 외부 클래스의 필드 접근에 용이하기 위함.
우리가 클래스를 다른 클래스 밖에서 쓰려면 그 클래스의 소속을 알려주어야 했다. (객체화)
내부 클래스의 필드를 사용하기 위해서는 외부 클래스에서 내부 클래스를 객체화 해야한다.

외부클래스명 객체명 = new 외부클래스생성자();
외부클래스명.내부클래스명 객체명 = 외부클래스객체명.new 내부클래스 생성자();
(해석 : 외부 클래스 안의 내부클래스 타입의 객체를 선언할건데, 이미 메모리에 올라가있는 외부클래스객체 안에 내부클래스의 생성자가 있기 때문에 new을 붙인다.)

주문이 들어와야 배달을 한다.
주문을 할 때 사용자의 주소,품목,전화번호가 전부 주문 클래스에 있을 것.
배달 클래스는 주문클래스 안에 있는 필드를 써야 할 것인데, 다른 데서 쓰지도 않는데도 자꾸 객체화를 해야할 것이다.

내부 클래스를 사용하는 이유

캡슐화

A클래스에서 b라는 작업이 자주 쓰이고, 이 작업은 B 클래스를 만들어야 쉽게 관리할 수 있음. 하지만 다른 클래스에서 b 작업이 필요 없거나(A클래스에서만 필요하거나), B클래스를 외부에 노출시키고 싶지 않을 때 캡슐화를 사용한다.
내부클래스를 외부클래스 안에 가둬놓은 다음, "나만 쓸거야!" 하는 거다.

내부 클래스는 GUI(Graphic User Interface)개발시 많이 사용됨.
예를 들어 a라는 버튼과 b라는 버튼이 있다고 하자. 두 버튼의 기능이 서로 다르다면 클래스를 별도로 만드는 것보다 내부 클래스로 만들어 사용하는 것이 적합할 것. 각각 클래스로 놓기에는 다른 데에서는 무쓸모인 것.


외부 클래스(OutClass) 안에 내부 클래스(innerClass)를 만들어보자.

package innerClass;

public class OutClass {

	int outData;

	public OutClass() {
		System.out.println("외부 클래스 생성자 호출됨.");
	}
	
	public void showOuter() {
		System.out.println("외부 클래스의 메서드 호출됨.");
	}
	
	public class innerClass {
		int inData;
		
		public innerClass() {
			System.out.println("내부 클래스의 생성자 호출됨.");
		}
		
		public void showInner() {
			outData = 20;
			
			System.out.println("내부 클래스의 메서드 호출됨.");
			System.out.println("outData : " + outData);
			// 내부에서 값을 변경한 것. 
			showOuter();
			// 외부의 메서드도 사용이 된다. 
		} // 내부에서 외부에 접근을 하고 있는 것. 외부 필드를 사용할 때 굉장히 용이하구나. 
	}
	
	// 한 페이지에서는 public class는 하나만 있어야한다 했다.
	// Outclass와 InnerClass는 현재 동격이 아니다.
	// InnerClass는 Outclass의 소속인 것. 얘도 하나의 필드로 쳐서 
	// 각 접근권한 제어자를 붙일 수 있다. 
	// Outclass가 크기 때문에 메인클래스로 인식이 된다.
	
	public static void main(String[] args) {
		OutClass out = new OutClass();
		// 출력값 : 외부 클래스 생성자 호출됨.
		OutClass.innerClass in = out.new innerClass();
		// 출력값 : 내부 클래스의 생성자 호출됨.
		// 내부클래스에 접근하는 방법이다. 
		in.showInner();
		// 출력값 : 
		//내부 클래스의 메서드 호출됨.
		//outData : 20
		//외부 클래스의 메서드 호출됨.	
	}
}

익명 클래스(Anonymous inner Class)

이름이 없는 클래스(일회성으로 사용하기 위함)
안드로이드에서 아주 많이 자주 쓰이는 문법

package anonyClass;

public interface Cafe {
	//메뉴판
	//판매
	void setMenu(String[] menu);
	String[] getMenu();
	void sell(String choice); 
	// 전부 앞에 abstract가 생략되어 있다. 
}

main으로 가보자

package anonyClass;

public class Starbucks {
	
	private String[] menu = {"아메리카노", "레몬티", "카푸치노"};
	private int[] arPrice = {5000, 8000, 9000};
	private int income;
	String choice;
	
	public String[] getMenu() {
		return menu;
	}



	public void setMenu(String[] menu) {
		this.menu = menu;
	}



	public int[] getArPrice() {
		return arPrice;
	}



	public void setArPrice(int[] arPrice) {
		this.arPrice = arPrice;
	}



	public int getIncome() {
		return income;
	}



	public void setIncome(int income) {
		this.income = income;
	}

// 외부에서 인터페이스 타입 Cafe로 받아옴. 등록하는 메서드이기 때문에
// 매번 재정의하는 인터페이스 타입으로 받아온 것임.
	public void registCafe(Cafe c, String choice) {
		c.setMenu(menu);
		System.out.println("카페 등록 완료");
		System.out.println("----Menu----");
		for (int i = 0; i < c.getMenu().length; i++) {
			System.out.println(i+1+ "." +c.getMenu()[i]);
			// 1.아메리카노 2.레몬티 3.카푸치노
		}
		c.sell(choice);
	}
	
	public static void main(String[] args) {
		Starbucks gangnam = new Starbucks();
		gangnam.registCafe(new Cafe() {
//		인터페이스라서 재정의해주어야 함. 값이기 때문에 이름이 없는 상태
//		매번 사용할 때마다 재정의해주어야 하는 애들은 이렇게 익명클래스로 사용된다.
//		다시 사용할게 아니니까. 
			@Override
			public void setMenu(String[] menu) {
				gangnam.menu = menu; 
			}

			@Override
			public void sell(String choice) {
				for (int i = 0; i < gangnam.getMenu().length; i++) {
					if(gangnam.getMenu()[i].equals(choice)) {
						gangnam.income += gangnam.arPrice[i];
					}
				}	
			}
			
			@Override
			public String[] getMenu() {
				return gangnam.menu;
			}
		},"카푸치노");
        // (,)콤마 앞까지가 new Cafe의 매개변수 
		System.out.println("카푸치노 주문 완료");
		System.out.println("현재 수익 : " + gangnam.getIncome() + "원" );
	}
 }

출력 결과

카페 등록 완료
----Menu----
1.아메리카노
2.레몬티
3.카푸치노
카푸치노 주문 완료
현재 수익 : 9000원
profile
코드를 두드리면 문이 열린다

0개의 댓글