본문 바로가기
공부/Java

[즐거운자바] 객체지향(5) - 추상클래스 + 접근제한자

by 다음에바꿔야지 2023. 10. 13.

<사용 목적>

일반적인 클래스와 그 클래스들의 공통된 특성을 정의하고 해당 클래스들이 구현해야 하는 메서드를 선언하는 데 사용됨. 

추상 메서드를 사용하면 서브클래스가 추상 클래스나 인터페이스의 메서드를 반드시 구현하도록 강제할 수 있음.

 

<특징>

1. 보통 1개 이상의 추상 메소드를 가진다. 추상 메소드는 {매서드 이름, 매개변수 목록, 반환 유형}만 정의하고 구현 내용은 제공하지 않는 메소드이다.(추상 메소드가 없어도 오류가 발생하진 않는다.) 아래 코드를 참고하자.

// 추상 클래스
abstract class Shape {
    // 추상 메서드 선언
    public abstract double calculateArea();
}

2. 추상 클래스는 직접 객체를 생성할 수 없다. 즉, 'new' 키워드를 사용하여 추상 클래스의 인스턴스를 만들 수 없다.

3. 부모가 가진 추상 메소드는 자식에서 꼭 구현해줘야 한다. 이러한 구현이 없으면 자식클래스도 추상 클래스가 된다.

 

<Template Method Pattern으로 추상 클래스 익히기>

디자인 패턴에는 여러 가지가 있는데, 나중에 꼭 찾아보기로 하고 일단 지금은 기본에 집중한다.

템플랫 메소드 패턴은 짧게만 설명하자면, 어떤 순서를 가지고 있고 그 순서대로 실행하는 디자인 패턴이다.

예제는 Controller의 종류가 여러 개일때, 실행 부분만 다른 코드로 구현되어 있는 상황이다. 이때 추상 클래스를 사용하는 방법을 알아보겠다.

package com.example.fw;

/*
Controller의 종류가 여러개
초기화 - 같은 코드
실행 - 다른 코드
마무리 - 같은 코드
*/

public abstract class Controller {
    // protected는 같은 package이거나 상속 받았을 경우 접근 가능. 
    // final이 붙으면 overriding 금지됨.
    protected final void init() {
    	System.out.println("초기화 하는 코드 ");
    }
    
    protected final void close() {
    	System.out.println("마무리 하는 코드 ");
    }
    
    protected abstract void run(); // 매번 다른 코드 
    
    // 내가 가지고 있는 메소드를 호출한다. 
    // 템플릿 메소드: 어떤 순서를 가지고 있고 그 순서대로 실행한다.
    public void execute() {
    	this.init(); // this 생략 가능 
        this.run();
        this.close();
    }
}

Controller라는 추상 클래스는 init(), close(), run(), execute() 메소드를 가지고 있다.

이 중 run()은 추상 메소드로 Controller마다 매번 다른 코드가 실행되어야 한다.

package com.example.myproject;

import com.example.fw.Controller;

public class FirstController extends Controller {
    @Override
    protected void run() {
    	System.out.println("별도로 동작하는 코드 11111");
    }
}

FirstController라는 클래스에 Controller를 상속받아, 추상 메소드인 run()을 오버라이딩해서 다른 코드가 실행되도록 했다.

package com.example.main;

import com.example.fw.Controller;
import com.example.myproject.FirstController;

public class ControllerMain {
    public static void main(String[] args) {
        Controller c1 = new FirstController();
        c1.excute();
    }
}

// 결과:
// 초기화 하는 코드 
// 별도로 동작하는 코드 11111
// 마무리하는 코드

ControllerMain 클래스를 만들어 main 메소드에 Controller를 참조하는 FirstController 인스턴스를 생성했다.

실행해보니, 정상 작동되었다 :)

 

<접근제한자>

접근제한자 클래스 내부 동일 패키지 하위 클래스 그외
public O O O O
protected O O O X
default O O X X
private O X X X