[Java/Kotlin] Abstract Class

Jay·2021년 1월 27일
0

Java&Kotlin

목록 보기
13/30
post-thumbnail

추상 클래스

  • 미완성된 클래스이다.
  • 미완성된 클래스는 미완성 된 메서드인 추상 메서드를 포함하고 있다.
  • 혼자서는 클래스의 역할을 못하지만, 새로운 클래스를 작성하는데에 있어서 바탕이 되는 부모 클래스로서의 중요한 의미를 갖는다. 클래스를 작성함에 있어 어느정도 작성된 상태에서 시작할 수 있기에.
  • 클래스 앞에 abstract 키워드를 붙인다.
abstract class Car {
  abstract void accelrate();
}
  • abstract 키워드가 있는 클래스라고 모두 구현해야 하는 것은 아니다. 단지 공유의 목적으로 abstract 클래스를 만드는 경우도 있기 때문에.

목적

  • 기존의 클래스에서 공통된 부분을 추상화하여 상속하는 클래스에게 구현을 강제화한다. 메서드의 동작은 구현하는 자식들에게 위임한다.
  • 추상 클래스는 동작을 포함하고 있지 않은 추상 메서드를 포함하기에 인스턴스를 생성할 수 없다.

특징

  • 추상 클래스는 추상 메서드가 아닌 일반 메소드, 멤버도 포함 할 수 있다.
  • 하지만, 추상 메서드를 하나라도 포함한다면 추상 클래스로 선언해야 한다.
abstract class Animal {
  abstract void cry();
}

class Cat extends Animal {
  @Override
  void cry(){
    System.out.println("냐옹냐옹 ~~!");
  }
}

class Dog extends Animal {
  @Override
  void cry(){
    System.out.println("멍멍 ~~!");
  }
}

public class Test{
  public static void main(String[] args){
    // Animal animal = new Animal();
    // 추상 클래스는 자체적으로 인스턴스를 생성할 수 없다. 불완전하기 때문에.
    
    Cat cat = new Cat();
    Dog dog = new Dog();
    
    cat.cry();
    dog.cry();
  }
}

추상 클래스인 Animal은 추상 메소드인 cry() 를 가지고 있으며, Animal 클래스를 상속받는 자식 클래스인 Dog, Cat 클래스는 cry() 메소드를 오버라이딩해야만 인스턴스를 생성할 수 있다.


추상 메서드!?

  • 선언부만 작성하고 구현부는 작성하지 않은 메서드, abstract 키워드가 붙는다.
  • 구현부를 작성하지 않는 이유는 메소드의 내용이 상속받은 클래스에 따라 달라질 수 있기 때문이다.
  • 사용 목적은 추상 메소드를 포함하는 클래스를 상속받는 자식 클래스가 반드시 추상 클래스를 구현하도록 강제하기 위함이다.
  • 추상 클래스를 상속받은 자식 클래스는 오버라이딩을 통해 조상인 추상 클래스의 추상 메소드를 모두 구현해야 한다.
  • 만약 자식 클래스에서 추상 메서드를 하나라도 구현하지 않는다면 자식 클래스 역시 추상 클래스로 지정해야 한다.

왜 사용할까?🙋‍♂️

근데 그래서 나는 추상 클래스가 뭔지 알겠다. 그러나 왜 추상화하는 지를 제대로 이해해보자.
자식 클래스에서 추상 클래스의 구현을 강제하기 위해서. 그리고 그 추상 클래스에는 공통적인 부분들을 추상화 시켜두었고 추상 메소드 역시 선언부만 존재하기에 구현은 자식 클래스에게 위임한다.
그래 이유는 알겠어. 구현을 강제. 근데 왜?👀

이는 객체지향의 개념을 조금더 생각해보면 답이 될 수 있다.
추상 클래스와 추상 메서드를 객체 지향의 관점에서 보자.

✅ 객체 지향 설계에선 구현해야 할 것들을 객체로 바라 본 후,
객체들 간의 연관 관계(is-a), 포함 관계(has-a) 로 풀어낸다는 점이 핵심이다.

추상 관계는 객체들 관의 연관 관계를 상속 관계로 정립하면서 생기는, 점차 상위 클래스를 정의하게 되면서 발생하는 "구체적인 행동 내용은 부모가 정할 수 없다" 를 묘사한다고 생각하면 된다.

✅ 부모 단계에서 추상화하여 "내 시점에선 행동을 특정할 수 없지만 자식 시점에선 반드시 구현되어야 하고 구현될 수 있는 행동이다" 라는 것을 설계 시점에서 명시하는 것이다.

이럼에도 이해가 안된다면 아래의 예시를 보자. 👋

만일 여러 도형 객체를 구현해야 하고, 넓이, 부피, 중심 좌표 등을 제공해줄 수 있게 해야 한다. 그럼 "원", "사각형", "삼각형" 등의 클래스는 추상화하여 "평면도형" 이라는 부모 클래스를 정의하고 상속받게 할 수 있다. "구", "직육면체", "삼각뿔" 등의 클래스는 "입체도형" 이라는 부모 클래스를 정의하고 상속받게 할 수 있다.
입체도형과 평면도형 클래스는 다시 추상화하여 "도형" 이라는 부모 클래스를 정의하고 상속 받게 설계하면 추상화를 완료하게 된다.
도형->평면도형->원 과 같은 형태가 된다.

넓이()나 부피() 같은 메소드는 최종 자식 클래스에선 구체적으로 구현해줄 수 있지만 평면도형, 입체도형 클래스 시점에선 이를 구현하기 힘들것이다. 따라서 이들을 추상 메소드로 선언해두고, 자식 클래스에서 실제로 구현해준다. 또 도형 입장에서는 무게중심 혹은 질량중심의 좌표를 담아두기 힘들다. 하지만 평면도형 클래스에선 무게중심의 좌표를, 입체도형 클래스에선 질량중심의 좌표를 담아둘 수 있을 것이다.

이런 식으로 본인의 클래스에서 공통적인 부분을 추출하여 추상 클래스를 만들 수 있고 자식이 구현해야하는 부분을 추상 메소드로 추출 할 수 있다.

열심히 궁금함을 찾다가 누군가 써주신 답변 글에서 위의 예시와 함께 정확한 답을 얻을 수 있었다.😃


🧐 단순히 추상클래스, 추상메서드가 뭔지, 언제 쓰는지 보다 정확히 왜 쓰고 추상화라는 개념과 객체지향적인 관점에서 어떤 행동인지 어떤 역할을 위함인지 아는게 더 중요한 것 같다.

Reference

profile
developer

0개의 댓글