[Java] 추상 클래스 (abstract class)와 추상 메서드(abstract method)의 개념


추상 클래스와 추상 메서드


 1) 추상 클래스

- 서브 클래스에게 공통 필드와 메서드를 상속해주는 용도로 사용한다.

- 그 자체로 인스턴스를 만들어 사용하지 않는 경우에

  "추상 클래스"로 선언한다.

- 예) Car 클래스는 Sedan, Truck, Bulldozer의 공통 기능을 모아둔 클래스이다.

 이 클래스를 직접 사용하려고 만든 것이 아니다.

 이와 같이 특히 generalization 과정에 생성된 수퍼 클래스인 경우

 주로 추상클래스로 선언한다.

      - 왜? 

        직접 사용하지 말라는 의미이다. 

        상속 받아 쓰라는 의미이다.

        단지 상속 해주는 역할을 한다는 의미이다.

- 실습

- Car 클래스와 Loader 클래스는 직접 사용하기 위해 만든 클래스가 이니다.

  서브 클래스의 공통 필드나 메서드를 관리하기 쉽도록 하기 위해 수퍼

  클래스로 정의한 것이다. 

  그래서 이 클래스들은 abstract로 선언하는 것이 마땅하다.



 2) 추상 메서드

- 서브 클래스 마다 기능을 다루는 방법이 다를 것 같으면

  굳이 수퍼 클래스에서 그 메서드를 정의하지 말라

- 또는 서브 클래스에게 특정 메서드를 반드시 구현하도록 강요(강제)하고 싶다면

  수퍼 클래스에서 그 메서드를 정의하지 말라!

- 이런 메서드인 경우,

   "추상 메서드"로 선언한다.

의미?

  - 서버 클래스를 만드는 개발자, 이 메서드를 반드시 구현하세요.

  - 서브 클래스를 만드는 개발자, 제가 이 메서드를 구현해 봐야 소용이 없을 것 같습니다.

  - 예) Car 클래스의 run() 메서드는 모든 서브 클래스에서 재정의 해야한다.

- 추상 메서드는 추상 클래스 만이 가질 수 있다.

  인스턴스가 생성되어 실제 동작되는 클래스는 추상 메서드를 가질 수 없다.




추상 클래스 Car와 추상 메서드 run()의 예제


public abstract class Car {
  protected String model;
  protected String maker;
  protected int cc;
  public Car() {
    super();
  }
 
  public Car(String model, String maker, int cc) {
    this.model = model;
    this.maker = maker;
    this.cc = cc;
  }
 
  // 이 메서드느 어차피 서브 클래스에서 무조건 재정의할 것이다.
  // 또는 재정의하도록 강제하고 싶다.
  // 그렇다면 여기서 코딩하지 말자
  // 단지 어떤 메서드인지 선언만 하라!
  // 추상 메서드는 구현할 수 없다.
  public abstract void run();
}


Car로부터 상속 받은 추상 클래스 Loader의 예제 
- 짐을 싣는 메서드를 구현


public abstract class Loader extends Car {
  Object storage;
  public Loader() {
    super();
  }
  public Loader(String model, String maker, int cc) {
    super(model, maker, cc);
  }
 
  // 서브 클래스에서도 그냥 사용할 수 없는 메서드라면,
  // 다음 메서드와 같이 수퍼 클래스에서 선언한다.
  public void load(Object obj) {
    this.storage = obj;
    System.out.printf("%s를 실었습니다.\n", obj);
  }

}


Loader로부터 상속 받은 일반 클래스 Sedan의 예제
- Car의 추상 메서드 run()을 오버라이딩한다. 


public class Sedan extends Loader {
  boolean auto;
  public Sedan(String model, String maker, int cc, boolean auto) {
    super(model, maker, cc);
    this.auto = auto;
  }
 
  // 상속 받은 메서드를 서브 클래스의 역할에 맞게끔 재정의하자! 오버라이딩
  public void run() {
    System.out.println("부웅~~ 부드럽게 달린다.");
  }
}



Loader로부터 상속 받은 일반 클래스 Truck의 예제
- Car의 추상메서드 run()과 Loader의 일반메서드 load()를 오버라이딩 한다.

public class Truck extends Loader {
  public Truck(String model, String maker, int cc) {
    super(model, maker, cc);
  }
  // 수퍼 클래스 Car의 run()을 오버라이딩 한다.
  public void run() {
    System.out.println("부왕~~ 힘차게 달린다.");
  }
  // 수퍼 클래스 Loader의 load()를 오버라이딩 한다.
  public void load(Object obj) {
    if (obj != null) {
      super.load(obj);
    } else {
      System.out.println("비었습니다.");
    }
  } 
  public void dump() {
    if (storage != null) {
      System.out.printf("%s를 내렸습니다.\n", this.storage);
      this.storage = null;
    } else {
      System.out.println("내릴 게 없습니다.");
    }
  }

}



* 결론!


- 추상 메서드는 추상 클래스 만이 가질 수 있다.

  인스턴스가 생성되어 실제 동작되는 클래스는 추상 메서드를 가질 수 없다.

- 추상 클래스는 어디까지나 유지보수를 하게 될 개발자에게 자식 클래스에서 

   메서드를 재정의하길 바라는 마음에서, 만들어진 문법이다.




블로그 이미지

필로그래머

,