클래스 내부에 다른 클래스를 두는 방법중 대표적인 2가지가 중첩 클래스(static class), 내부 클래스(inner class)가 있다.
부제에 대한 답 : 중첩 클래스는 가시성을 제한하거나, Item, Node, Element, ViewHolder 같은 일반적인 이름을 사용하면서 정돈된 상태를 유지하는데 아주 유용하다.
왜 일까?
그전에 중첩 클래스와 내부 클래스에 대해 간단하게 알아보자
중첩 클래스
물품(item)의 비용을청구하는 Invoice 클래스가 있다고 생각하고, 물품에는 설명, 수량, 단가가 포함되어 있다
이를 중첩 클래스로 표현하면 아래와 같이 된다. 그리고 public static 으로 선언한 것 말고는 내부에 클래스를 선언하는 것과 크게 다른 것이 없어보인다
public class Invoice {
public static class Item { // 중첩 클래스 Item
String des;
int quantity;
double price;
double getAllPrice() {
return quantity * price;
}
// 여기 필드에서는 items 에 접근할 수 없음 당연히 static 멤버 변수, 메소드만 참조 가능
}
private List<Item> items = new ArrayList<>();
public void add(Item item){
items.add(item);
}
// something...
}
하지만 실제로 사용할 때는 Invoice.Item 을 명시적으로 붙여 객체를 명확하게 생성할 수 있다.
결과적으로 클래스 중첩(static)은 Item 클래스가 Invoice 내부에 들어있는 물품을 표현한다는 사실을 분명하게 해준다.
public static void main(String[] args) {
Invoice invoice = new Invoice();
Invoice.Item item = new Invoice.Item(); // Item 클래스가 Invocie 클래스 내부에 존재한다는 것을 명확하게 알 수 있다
invoice.add(item);
}
Recyclerview.Adapter 내부에 만들어서 사용하는 VIewHolder 클래스도 내부에 존재한다는 사실을 명확하게 사용하기 위해 존재한다.
(물론 ViewHolder 가 거대해질 것 을 생각해서 따로 분리해서 사용하는 경우도 많다.)
CustomRecyclerviewAdapter extends RecyclerView.Adapter<CustomRecyclerviewAdapter.CustomViewHolder>{
// TODO something ...
public static CustomViewHolder extends RecyclerView.ViewHolder {
// TODO something ...
}
@Override
public CustomRecyclerviewAdapter.CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// TODO something
}
@Override
public void onBindViewHolder(CustomRecyclerviewAdapter.CustomViewHolder holder, int position) {
// TODO something
}
}
CustomRecyclerviewAdapter.CustomViewHolder 아주 명확하다!
내부 클래스
그렇다면 static 제어자를 빼면 어떻게 될까?
내부 클래스의 메서드는 외부 클래스의 인스턴스 변수에 접근할 수 있다.
바로 이 점이 내부 클래스를 중첩 클래스와 다르게 만드는 요인이다.
예를 보자
public class Invoice {
public class Item { // 내부 클래스 Item
String des;
int quantity;
double price;
double getAllPrice() {
return quantity * price;
}
void removeItem(int index) { // Item 클래스에서 Invoice 필드에 접근 가능
items.remove(index);
}
void add(Item item){ // Item 클래스에서 Invoice 필드에 접근 가능
items.add(item);
}
}
private List<Item> items = new ArrayList<>();
// something...
}
Item 클래스에서 Invoice 의 필드에 접근하고 있다.
또한
public class Item { // 내부 클래스 Item
String des;
int quantity;
double price;
double getAllPrice() {
return quantity * price;
}
void removeItem(int index) { // Item 클래스에서 Invoice 필드에 접근 가능
items.remove(index);
}
void add(Item item){ // Item 클래스에서 Invoice 필드에 접근 가능
items.add(item);
}
public boolean isSame(Invoice invoice) {
return Invoice.this == invoice;
}
}
isSame 함수를 추가하여 현재 아이템이 같은 Invoice 에 포함되어 있는지 확인도 가능하다.
이런식으로 외부클래스를 자유롭게 접근하여 코드를 작성할 수 있다.
'Kotlin & Java' 카테고리의 다른 글
인터페이스의 정적(static) 메서드와 기본(default) 메서드 (0) | 2020.03.02 |
---|---|
타입 변환과 instanceof 연산자 Tips (0) | 2020.03.02 |
자주 사용하는 String 클래스 함수 (0) | 2020.02.29 |
자바 문자열 고찰 및 생각의 힘 (0) | 2020.02.28 |
자바 기본 타입 (Primitive type) (0) | 2020.02.27 |