[Java] 익명객체

재피터노트북·2022년 10월 20일
0

익명객체

클래스를 선언할 때 일반적으로 클래스 이름과 동일한 소스 파일을 생헝하고 클래스 선언합니다. 한번 선언해놓고 여러 곳에서 객체를 만들어 사용하고 싶을 때 간단히 클래스 이름으로 생성자를 호출할 수 있기 때문입니다. 그런데 클래스 이름이 없는 객체도 있습니다. 이것을 익명(annoymous)객체라고 합니다.

익명 자식객체 (extends)

  • 일반적인 상속을 이용한 객체 사용법

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 부모클래스(매개값, ...) {
	// 필드
	// 메소드
	// 생성자는 가질 수 없습니다.
};

예시(부모 클래스 CPU)

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);
    }
}

CPU 클래스를 활용하는 Computer 클래스

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); // 메소드(매개 변수)

3. 익명 구현 객체(impleents)

인터페이스 타입으로 필드나 변수를 선언하고, 구현 객체를 초기값으로 대입하는 경우 구현 클래스가 재사용되지 않고, 오로지 해당 필드와 변수의 초기값으로만 사용하는 경우라면 (일회용) 익명 구현 객체를 초기값으로 대입하는 것이 좋습니다.

익명 구현 객체 생성

인터페이스 [필드|변수] new 인터페이스() {
	// 인터페이스에 선언된 추상 메소드의 실체 메소드 선언
	// 필드
	// 메소드
};

예시 (인터페이스 OnEvent)

public interface OnEvent {
    void on();
}

OnEvent 인터페이스를 활용하는 MacBook 클래스

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)"));
profile
난 이 재 선

0개의 댓글