클래스를 선언할 때 일반적으로 클래스 이름과 동일한 소스 파일을 생헝하고 클래스 선언합니다. 한번 선언해놓고 여러 곳에서 객체를 만들어 사용하고 싶을 때 간단히 클래스 이름으로 생성자를 호출할 수 있기 때문입니다. 그런데 클래스 이름이 없는 객체도 있습니다. 이것을 익명(annoymous)객체라고 합니다.
public class Parent {
String name = "Parent Class";
void methodParent() {
System.out.println("class name(Parent): " + this.name);
}
}
public class Child extends Parent {
String name = "Child Class";
@Override
void methodParent() {
System.out.println("class name(Child): " + this.name);
System.out.println("class name(Parent): " + super.name);
}
}
Parent parent = new Child();
parent.methodParent();
다형성을 위해 부모 타입으로 필드나 변수를 선언하고, 자식 객체를 초기값으로 대입하는 경우 자식 클래스가 재사용되지 않고, 오로지 해당 필드와 변수의 초기값으로만 사용할 경우라면 (일회용) 익명 자식 객체를 생성해서 초기값으로 대입하는 것을 권장합니다.
부모클래스 [필드|변수] = new 부모클래스(매개값, ...) {
// 필드
// 메소드
// 생성자는 가질 수 없습니다.
};
public class CPU {
private String modelName;
private int coreCnt;
public CPU(String modelName, int coreCnt) {
this.modelName = modelName;
this.coreCnt = coreCnt;
}
public String getModelName() {
return modelName;
}
public int getCoreCnt() {
return coreCnt;
}
public void cpuSpec() {
System.out.println(this.coreCnt);
System.out.println(this.modelName);
}
}
public class Computer {
// 필드
CPU fieldCpu = new CPU("intel-001", 8) {
@Override
public void cpuSpec() {
System.out.println("---- Intel CPU STATUS ----");
System.out.println("모델명: " + getModelName());
System.out.println("코어 수: " + getCoreCnt());
System.out.println("---- Intel CPU STATUS ----" + '\n');
}
};
// 로컬 변수
void methodA() {
CPU localCpu = new CPU("amd-001", 4) {
@Override
public void cpuSpec() {
System.out.println("---- AMD CPU STATUS ----");
System.out.println("모델명: " + getModelName());
System.out.println("코어 수: " + getCoreCnt());
System.out.println("---- AMD CPU STATUS ----" + '\n');
}
};
localCpu.cpuSpec();
}
// 매개 변수
void methodB(CPU cpu) {
cpu.cpuSpec();
}
}
Computer computer = new Computer();
computer.fieldCpu.cpuSpec(); // 필드
computer.methodA(); // 메소드(로컬 변수)
CPU IntelCpu = new CPU("intel-003", 16) {
@Override
public void cpuSpec() {
System.out.println("---- Intel CPU STATUS ----");
System.out.println("모델명: " + getModelName());
System.out.println("코어 수: " + getCoreCnt());
System.out.println("---- Intel CPU STATUS ----" + '\n');
}
};
computer.methodB(IntelCpu); // 메소드(매개 변수)
인터페이스 타입으로 필드나 변수를 선언하고, 구현 객체를 초기값으로 대입하는 경우 구현 클래스가 재사용되지 않고, 오로지 해당 필드와 변수의 초기값으로만 사용하는 경우라면 (일회용) 익명 구현 객체를 초기값으로 대입하는 것이 좋습니다.
인터페이스 [필드|변수] new 인터페이스() {
// 인터페이스에 선언된 추상 메소드의 실체 메소드 선언
// 필드
// 메소드
};
public interface OnEvent {
void on();
}
public class MacBook {
// 필드
OnEvent fieldOnEvent = new OnEvent() {
@Override
public void on() {
System.out.println("Mac Book ON(Field)");
}
};
// 로컬 변수
void methodA() {
OnEvent localOnEvent = new OnEvent() {
@Override
public void on() {
System.out.println("Mac Book ON(Local Variable)");
}
};
localOnEvent.on();
}
// 매개 변수
void methodB(OnEvent onEvent) {
onEvent.on();
}
}
MacBook macBook = new MacBook();
macBook.fieldOnEvent.on(); // 필드
macBook.methodA(); // 로컬 변수
// 매개 변수
macBook.methodB(new OnEvent() {
@Override
public void on() {
System.out.println("Mac Book ON(Parameter)");
}
});
// 인터페이스가 추상 메소드가 1개인 함수적 인터페이스라면 람다를 활용할 수도 있습니다.
macBook.methodB(() -> System.out.println("Mac Book ON(Parameter & Lambda)"));