Java Nested - 내부 클래스 활용
예제코드를 통해 내부 클래스를 어떻게 활용하는지 살펴보자.
내부 클래스 리팩토링 전
Engine.class
// Car 에서만 사용
public class Engine {
private Car car;
public Engine(Car car) {
this.car = car;
}
public void start() {
// 배터리 충전 레벨 단위가 무엇인지 알아야 구동하는 계획으로 예상한다.
System.out.println("충전 레벨: " + car.getChargeLevel());
System.out.println(car.getModel() + " 엔진을 구동하기");
}
}
Car.class
public class Car {
private String model;
private int chargeLevel;
private Engine engine;
public Car(String model, int chargeLevel){
this.model = model;
this.chargeLevel = chargeLevel;
this.engine = new Engine(this);
}
// Engine 에서만 사용하는 메소드
public String getModel() {
return model;
}
// Engine 에서만 사용하는 메소드
public int getChargeLevel() {
return chargeLevel;
}
public void start() {
engine.start();
System.out.println(model + " 시작 완료");
}
}
- Car 클래스는 엔진에 필요한 메소드들을 제공. 다음 메소드는 엔진에서만 사용하며 다른 곳에서는 사용하지 않는다.
- getModel()
- getChargeLevel()
- 결과적으로 Car 클래스는 Engine 에서만 사용하는 기능을 메소드를 추가해 모델 이름과 충전 레벨을 외부에 노출한다.
- Engine에서 Car 클래스 멤버필드 출력하는 메소드를 호출용도로만 사용
- 결과적으로 Car 클래스는 메소드가 공개되어 Engine 이 아닌 곳에서도 사용 가능. 개발자 생각에는 허용하고 싶지 않음
Main.class
public class Main {
public static void main(String[] args) throws Exception {
Car myCar = new Car("Model Y", 100);
myCar.start();
}
}
충전 레벨: 100
Model Y 엔진을 구동하기
Model Y 시작 완료
내부 클래스 리팩토링 후
내부 클래스 사용으로 간결해진 코드를 살펴보자
Car.class
public class Car {
private String model;
private int chargeLevel;
private Engine engine;
public Car(String model, int chargeLevel){
this.model = model;
this.chargeLevel = chargeLevel;
this.engine = new Engine();
}
public void start() {
engine.start();
System.out.println(model + " 시작 완료");
}
public class Engine {
public void start() {
// 배터리 충전 레벨 단위가 무엇인지 알아야 구동하는 계획으로 예상한다.
System.out.println("충전 레벨: " + chargeLevel);
System.out.println(model + " 엔진을 구동하기");
}
}
}
Main.class
public class Main {
public static void main(String[] args) throws Exception {
Car myCar = new Car("Model Y", 100);
myCar.start();
}
}
충전 레벨: 100
Model Y 엔진을 구동하기
Model Y 시작 완료
리팩토링 전에는 모델 이름과 충전 레벨을 외부에 노출되었다. Car 클래스 정보들이 외부로 노출되는 것이므로 캡슐화가 되었다고 보기 어렵다.
세부적인 코드는 Car 클래스에서 Engine의 멤버필드를 불려올려면 getter 들을 호출하여야하는데, 내부 클래스 사용으로 불필요한 getter를 제거하였다.
중첩 클래스 용도
언제 사용하는가?
- 중첩 클래스는 특정 클래스가 다른 한 클래스 안에서만 사용한다. 이 중첩 클래스가 긴밀하게 연결되어 있어서 사용한다.
- 만약 외부 여러 곳에서 특정 클래스를 사용하고 있다면 그것을 중첩 클래스로 사용하면 안된다.
중첩 클래스 장점
- 논리적 그룹화
- 특정 클래스가 다른 하나의 클래스 안에서만 사용하는 것은 그 클래스의 멤버필드와 메소드가 사용 가능하므로 논리적 그룹화가 된다.
- 패키지 오픈한 경우 불필요한 특정 클래스가 노출되지 않는다.
- 캡슐화
- 중첩 클래스는 바깥 클래스의 private 멤버로 접근할 수 있으며, 캡슐화에 불필요한 public 메소드를 제거 가능하다.