추상클래스(Abstract class)

임준철·2021년 4월 11일
1

OOPAdvance

목록 보기
2/4

추상 클래스란

  • 일부 메소드가 구현되지 않고, 선언만 되어있는 클래스
    • 자식 클래스에서 이것을 반드시 구현하게끔 강제하는 것
    • 필요한 모든 클래스가 구현될 수 있도록 하여 안정성을 높이는 효과를 가져온다.
  • 일반 클래스의 공통적인 부분을 추출해 어느정도 규격(틀)을 잡아 놓는 추상적인 클래스이다.
  • 일반 클래스는 실제 객체를 생성할 정도의 구체성을 가지는 반면, 추상클래스는 아직 메서드와 내용이 추상적이기 때문에
    객체를 생성할 수 없다.

추상클래스 특징

  • 메소드와 클래스에 abstract 예약어를 사용한다.
  • 추상클래스는 new(인스턴스화) 할 수 없다.
  • 추상메소드가 없어도 abstract 키워드를 사용하면 추상클래스가 된다
  • 생성자를 가질 수 있고, 일반 메소드도 가질 수 있다.
  • 생성자를 갖지만, 객체 생성이 불가능하다. 그런데 구현된 자식클래스의 객체는 받을 수 있다.
  • 추상클래스의 변수를 초기화 할 수 있다.(자동 초기화도 된다.)
  • 공통적으로 사용할 수 있는 필드와 메서드를 공통적으로 추출해 만들어진 클래스이다.
  • 구현해야하는 메소드들은 상위 클래스에서 선언을 해놓고,구현의 책임을 하위클래스에 위임한다.
  • 하나의 추상메소드라도 포함을 하면 추상 클래스가 되야 한다.
    • 모든 메소드가 구현되있다고 해도 클래스에 abstract 키워드를 사용하면 추상 클래스가 된다.
  • 자기 자신의 객체를 생성하지 못하는 거 외에는 일반클래스와 비슷하다.
  • 인터페이스와의 차이점은 멤버 변수를 갖고 있느냐 없느냐의 차이.

추상클래스 사용하기

  • 추상클래스는 단독으로 사용되는 것이 아니라 상위 클래스로서 사용된다.
    • 추상 메소드는 하위 클래스가 구현해야하는 메소드이다.
    • 구현된 메소드는 하위 클래스가 공통으로 사용하는 기능의 메소드
      하위 클래스에 따라 재정의할 수 있다.
  • 추상메소드는 하위클래스에서 강제적으로 구현을 해야하지만,
    구현된메소드(일반메소드)들은 하위 클래스에 따라 재정의할 수도 있고, 안해도 상관이 없다.

추상클래스의 사용 용도

  1. 공통된 필드와 메소드를 통일할 목적으로 사용한다.

    • 추상클래스에서 미리 필드와 메서드를 정의해 놓는다면, 실체클래스(일반클래스)에서는
      추상클래스의 필드와 메소드명을 변경할 수 없고 그대로 받아 사용해야 구현해야 한다.
      따라서 필드와 메소드의 이름을 통일시켜주고 유지보수성을 높일 수 있다.
  2. 실체클래스 구현시, 시간 절약이 가능하다.

    • 필드와 메소드를 정의해 놓은 추상클래스가 있다면, 예를 들어 자동차를 구현해야 할 때
      추상클래스를 기반으로 필요한 부분은 추가해서 클래스를 구현할 수 있다.
      (없다면 결국 내가 추상클래스를 구현해야 하는 것이 아니냐 하면 이미 회사에 이런 것들을 구현하는
      아키텍쳐들이 설계를 해놓았을 것이다.)
  3. 규격에 맞는 실체 클래스 구현

    • 추상클래스에서 사용해야 할 필드와 메소드들을 정의해 놓으니, 이것을 토대로 코드를 작성할 때,
      통일성 있는 규격 안에서 실체 클래스를 구현할 수 있기 때문이다.
abstract class AbstractFoo{
    int x, y;

    public void method(){
        System.out.println("method");
    }
                                       //세미콜론을 잊지 말아야 합니다.
    public abstract void abstractMethod(); 
    // 선언만 하고 구현하지 않음. Virtual method call이여서 부모메소드는 비어있음.
}

class Foo extends AbstractFoo{

    @Override
    public void abstractMethod() {
        System.out.println("implemented abstractMethod");
    }
}

public class AbstractClass {
    public static void main(String[] args) {
       // AbstractFoo afoo = new AbstractFoo() 
       //추상 클래스는 객체 생성이 불가합니다. 구현이 안되있으니 인스턴스화가 안된다.
        Foo foo = new Foo();
        foo.abstractMethod();

        AbstractFoo afoo = (AbstractFoo)foo;
        afoo.abstractMethod(); // virtual method call
        //추상클래스는 객체 생성은 불가하지만, 구현된 자식클래스의 객체는 받을 수 있다.
    }
}

템플릿 메서드

  • 템플릿 : 틀이나 견본을 의미
  • 템플릿 메소드 : 추상메소드나 구현된 메소드를 활용하여 전체의 흐름(시나리오)를 정의 해 놓은 메소드 final로 선언하여 재정의 할 수 없게 한다.

템플릿 매서드 패턴

  • 디자인 패턴의 일종으로 프레임워크에서 많이 사용되는 설계패턴이다
  • 추상클래스로 선언된 상위클래스에서 추상메소드를 이용하여 전체 구현의 흐름을 정의하고
    구체적인 각 메소드 구현은 하위클래스에 위임함
  • 하위클래스가 다른 구현을 했 다고 해서 템플릿 메소드에 정의된 시나리오대로 수행됨.

템플릿 메소드 예제

  • Car 클래스
public abstract class Car {
    public abstract void drive();
    public abstract void stop();

    public void startCar(){
        System.out.println("시동을 켭니다.");
    }
    public void turnOff(){
        System.out.println("시동을 끕니다.");
    }
    public void washCar(){ }
    //아무 기능이 없어 여기서는 수행을 하지 않고 하위 클래스에서 재정의해서 사용.
    // 모든 하위클래스에서 구현을해야하는 거라면 abstract를 사용하지만
    // 모든 하위클래에서 사용하지 않으면 이렇게 사용한다.
    // 기능의 확장이 가능함

    //템플릿 메소드
    final public void run(){ //재정의할 수 없게 final 키워드 사용.
        startCar();
        drive();
        stop();
        turnOff();
        washCar();
    }
}
  • AICar
public class AICar extends Car {
    @Override
    public void drive() {
        System.out.println("자율 주행합니다.");
        System.out.println("자동차가 스스로 방향을 바꿉니다.");
    }

    @Override
    public void stop() {
        System.out.println("스스로 멈춥니다.");
    }

    @Override
    public void washCar(){
        System.out.println("자동 세차합니다.");
    }
}
  • ManualCar
public class ManualCar extends Car {
    @Override
    public void drive() {
        System.out.println("운전자가 주행합니다..");
        System.out.println("운전자가 방향을 바꿉니다.");
    }

    @Override
    public void stop() {
        System.out.println("운전자가 멈춥니다.");
    }
}
  • CarTest 클래스
public class CarTest {
    public static void main(String[] args) {
        Car aiCar = new AICar();
        aiCar.run();
        System.out.println("============");
        Car manualCarnuCar = new ManualCar();
        manualCarnuCar.run();
    }
}

final 예약어

  • fianl 변수는 값이 변경될 수 없는 상수이다.
  • public static final double PI = 3.14;
  • 오직 한번만 값을 할당 할 수 있음
  • final 메소드는 하위 클래스에서 재정의(overriding) 할 수 없음.
    final 클래스는 더 이상 상속되지 않음
  • 상속이 됬을 때 문제가 될 수 도 있고 고유한 기능이 있는 경우 상속할 일이 없다 하면 final을 붙이면 된다.
    public static final 상수 값 정의하여 사용하기
  • 프로젝트 구현 시 여러 파일에서 공유해야 하는 상수 값은 하나의 파일에 선언하여 사용하면 편리하다.

profile
지금, 새로운 문을 열자! 문 저편에 무엇이 있을지 두렵더라도!!

0개의 댓글