프로그래밍/JAVA
24 내부클래스와 익명클래스
윤지(●'◡'●)
2021. 4. 15. 10:28
반응형
내부클래스(inner class)
내부 클래스는 말 그대로, 클래스 내부에 선언된 클래스이다.
클래스 내부에 클래스를 선언하여 외부 클래스의 필드 접근에 용이하기 위한
내부 클래스의 필드를 사용하기 위해서는 외부 클래스에서 내부클래스를 객체화 해야한다.
[내부 클래스 객체화 문법]
외부클래스명 외부객체명 = new 외부클래스생성자();
외부클래스명.내부클래스명 내부객체명 = 외부객체명.new 내부클래스 생성자();
아래 예시를 보면, 내부클래스에서 외부클래스의 메소드, 변수에 접근이 용이한 것을 확인 할 수 있다.
package inner;
class Out {
int outData;
public Out() {
System.out.println("외부 생성자 호출됨");
}
void printOut() {
System.out.println("외부 클래스 메소드 호출됨");
}
class In{
int inData;
public In() {
System.out.println("내부 생성자 호출");
}
void printIn() {
printOut(); // 외부 클래스 메소드에 접근가능
outData = 100; // 외부 클래스 변수에 접근가능
System.out.println(outData);
}
}
}
public class InnerTest {
public static void main(String[] args) {
Out out = new Out();
Out.In in = out.new In();
}
}
내부클래스를 사용하는 이유
- 캡슐화 ( 쉽게 말하면, 숨기기위해서 )
ex)
A라는 클래스에서 a뿐만 아니라 b라는 작업도 자주 쓰이고, 이 작업은 B 클래스를 만들어야 쉽게 관리할 수 있다.
하지만 다른 클래스에서는 b작업이 쓰이지 않거나, B클래스를 외부에 노출 시키고 싶지 않을 때
내부 클래스로 선언한다.
익명 클래스(anonymous inner class)
이름이 없는 클래스(일회성으로 사용되기 위함)로 정의와 생성을 동시에 한다.
따라서 생성자를 선언할 수도 없으며, 오로지 단 하나의 클래스나 단 하나의 인터페이스를 상속받거나 구현할 수 있다.
이러한 익명 클래스는 매우 제한적인 용도에 사용되며, 구현해야 하는 메소드가 매우 적은 클래스를 구현할 때 사용된다.
new 조상클래스이름(){
// 멤버선언
}
//or
new 구현인터페이스이름(){
// 멤버선언
}
바로 예시로 살펴보자 : )
[문제]
스타벅스 체인점을 여러개 오픈한다.
스타벅스 본사에서는 새롭게 오픈한 매장의 메뉴와 판매방식이 필요하다.
체인점 오픈 시 반드시 스타벅스 본사에 등록해야한다.
1. Cafe interface
// 객체들이 반드시 구현해야할 틀 제공
public interface Cafe {
String [] getMenu();
void sell(String choice);
}
2. CafeAdapter class
// 인터페이스의 추상메소드 중, 강제성을 없애고 싶은 메소드 구현
public abstract class CafeAdapter implements Cafe{
@Override
public void sell(String choice) {;}
}
3. Starbucks class
public class Starbucks {
//객체별 본사에 등록하는 메소드(객체별로 단 한번만 사용)
void register(Cafe c) { // 외부에서 Cafe 타입을 전달 받음, 구현되지 않은 추상 메소드가 구현된 후 전달
String [] menu = c.getMenu();
for (int i = 0; i < menu.length; i++) {
System.out.println(i + 1 + ". " + menu[i]);
}
// Adapter 사용 시 sell()을 구현하지 않기때문에
if(!(c instanceof CafeAdapter)) {
// sell()을 구현한 Cafe 타입만 들어옴
c.sell("아메리카노");
}
}
}
4. Road main class
public class Road {
public static void main(String[] args) {
Starbucks gangnam = new Starbucks();
// Cafe가 인터페이스이기 때문에 강제성이 있는 추상 메소드를 반드시 구현해야 한다.
// 메소드를 선언하기 위해서는 반드시 클래스 안에서 선언해야 하고,
// 열린 클래스 중괄호에는 이름이 없으며, 메소드 안에 선언된 내부 클래스 이다.
// 이를 anonymouse inner class 라고 한다.
// 소괄호 내 중괄호 형태
// gangnam.register(new Cafe() { <---- 바로 이 중괄호가 익명 클래스 중괄호
gangnam.register(new Cafe() {
@Override
public void sell(String choice) {
// 제작된 메뉴(getMenu()) 중 고객이 주문한 메뉴(choice)를 비교 후 일치하면 판매완료
for (int i = 0; i < getMenu().length; i++) {
if(getMenu()[i].equals(choice)) {
System.out.println(choice + " 판매 완료");
}
}
}
@Override
public String[] getMenu() {
String [] menu = {"아메리카노","카페라떼","빵","홍차라떼"};
//제작된 메뉴판 리턴
return menu;
}
});
// 무료나눔
Starbucks jamsil = new Starbucks();
jamsil.register(new CafeAdapter() {
@Override
public String[] getMenu() {
String [] menu = {"아메리카노","카페라떼","빵","홍차라떼"};
return menu;
}
});
}
}
실행결과
1. 아메리카노
2. 카페라떼
3. 빵
4. 홍차라떼
아메리카노 판매 완료
1. 아메리카노
2. 카페라떼
3. 빵
4. 홍차라떼
반응형