자바

추상 메서드, 추상 클래스, 익명 내부 클래스[Java]

연향동큰손 2025. 3. 12. 16:17

 

 

추상 메서드란 메서드의 선언만 있고 구현이 없는 메서드를 말한다.

 

즉, 구체적인 동작이 정의되지 않은 메서드로, 반드시 추상 클래스(abstract class) 또는 인터페이스(interface)에서만 선언할 수 있다.

 

그리고 하나 이상의 추상 메소드를 포함하는 클래스를 가리켜 추상 클래스(abstract class)라고 한다.

 

 

간단한 예제를 통해서 알아보자.

 

추상 메서드 추상 클래스를 이용하지 않았을때

 

@Slf4j
public class TemplateMethodTest {

    @Test
    void templateMethodV0(){
        logic1();
        logic2();
    }

    private void logic1(){
        long startTime = System.currentTimeMillis();
        //비즈니스 로직 실행
        log.info("비즈니스 로직1 실행");

        //비즈니스 로직 종료
        long endTime =  System.currentTimeMillis();
        long result = endTime - startTime;
        log.info("resultTime={}",result);
    }
    private void logic2(){
        long startTime = System.currentTimeMillis();
        //비즈니스 로직 실행
        log.info("비즈니스 로직2 실행");

        //비즈니스 로직 종료
        long endTime =  System.currentTimeMillis();
        long result = endTime - startTime;
        log.info("resultTime={}",result);
    }
}

 

 

위 코드를 보면 logic1과 logic2가 log에 대한 정보만 다르고 모두 반복되는 코드라는 것을 확인할 수 있다.

 

이때, 반복되는 코드로 인해 코드에 대한 가독성이 떨어져서 이해도가 떨어질 수 있다.

 

이러한 상황에 추상 클래스와 추상 메서드를 사용하면 반복되는 코드를 줄일 수 있다.

 

추상 메서드, 추상 클래스 사용했을때

 

 

<추상 클래스 AbstractTemplate>

@Slf4j
public abstract class AbstractTemplate {

    /**
     * 템플릿 메서드 패턴을 적용한 실행 메서드.
     * 실행 시간을 측정하면서 비즈니스 로직(call 메서드)을 실행함.
     */
    public void execute(){
        long startTime = System.currentTimeMillis(); 

        // 비즈니스 로직 실행 (하위 클래스에서 구현)
        call();

        // 실행 종료 시간 기록
        long endTime =  System.currentTimeMillis();
        long result = endTime - startTime; // 총 실행 시간 계산

        // 실행 시간 로깅
        log.info("resultTime={}", result);
    }

    /**
     * 추상 메서드: 실제 비즈니스 로직은 하위 클래스에서 구현해야 함.
     */
    protected abstract void call();

}

 

로그에 대한 정보는 추상 메서드인 call() 메서드로 빼줘서 logic1과 logic2를 다르게 구현해야한다.

 

 

<logic1에 대한 추상 클래스 SubClassLogic1>

@Slf4j
public class SubClassLogic1 extends AbstractTemplate{
    @Override
    protected void call() {
        log.info("비즈니스 로직1 실행");
    }

}

 

추상 클래스를 상속받아서 추상 메서드를 오버라이드 해줌으로써 추상 메서드 구현이 가능해진다.

 

<logic2에 대한 추상클래스 SubClasslogic2>

@Slf4j
public class SubClassLogic2 extends AbstractTemplate{
    @Override
    protected void call() {
        log.info("비즈니스 로직2 실행");
    }
}

 

 

템플릿 메서드 페턴을 적용했기 때문에 AbstractTemplate 클래스를 상속받은 SubClassLogic1과 SubClassLogic2 가 각각 call()메서드를 다르게 구현하여 반복되는 코드를 줄이고 유지보수 또한 쉬워지게 된다!

@Slf4j
public class TemplateMethodTest {
    @Test
    void templateMethodV1(){
        AbstractTemplate template1 = new SubClassLogic1();
        template1.execute();

        AbstractTemplate template2 = new SubClassLogic2();
        template2.execute();
    }
}

 

 


익명 내부 클래스( Anonymous Inner Class )

위 예시와 같이 별도의 클래스를 선언하여 추상 메서드를 오버라이드 하는 방법도 있지만,

 

익명 내부 클래스를 사용하여 추상 메서드를 즉석에서 구현하는 방법도 있다.

 

@Test
void templateMethodV2(){
    AbstractTemplate template1 = new AbstractTemplate() {
        @Override
        protected void call() {
            log.info("비즈니스 로직1 실행");
        }
    };
    log.info("클래스 이름1={}",template1.getClass());
    template1.execute();

    AbstractTemplate template2 = new AbstractTemplate() {
        @Override
        protected void call() {
            log.info("비즈니스 로직2 실행");
        }
    };
    log.info("클래스 이름2={}",template2.getClass());
    template2.execute();
}

 

 

익명 내부 클래스는 재사용이 필요없는 일회성 클래스에서 사용하는 것이 가독성과 유지보수 측면에서 유리하고,

 

반복적으로 사용할 경우 별도의 클래스를 만들어서 상속해주는 것이 좋다.

 

 

'자바' 카테고리의 다른 글

동시성 문제를 해결하기 위한 ThreadLocal[java]  (0) 2025.03.05
Thread란 무엇인가[Java]  (1) 2025.03.02
예외  (0) 2025.02.02
HashMap  (0) 2024.02.21
Iterator  (2) 2024.02.21