가상 또는 추상 클래스는 일반 클래스와 달리 객체를 생성할 수 없다!?

추상 클래스나 객체라는 개념, 처음 접하면 "붕어빵 틀이 있는데 왜 붕어빵을 못 만든다는 거지?" 싶어서 충분히 헷갈릴 수 있어요. 아주 핵심만 짚어서 쉽게 설명해 드릴게요!

1. '객체(Object)'란 무엇인가?

컴퓨터 프로그래밍에서 객체는 "실제로 메모리에 존재하며 일을 하는 실체"를 말해요.

  • 클래스: 설계도 (예: 자동차 설계도)
  • 객체: 설계도를 보고 실제로 만든 물건 (예: 내 주차장에 있는 아반떼, 옆집 테슬라)

설계도만 가지고는 도로를 달릴 수 없죠? 실제로 공장에서 찍어낸 '실물(객체)'이 있어야 운전을 할 수 있는 것과 같은 이치입니다.

2. 왜 추상 클래스는 객체를 못 만들까?

가장 큰 이유는 "미완성 설계도"이기 때문이에요.

예를 들어, 제가 당신에게 "동물(Animal) 한 마리만 그려보세요"라고 했다고 가정해 봅시다. 당신은 강아지를 그릴 수도, 고양이를 그릴 수도 있지만, '강아지도 고양이도 아닌 그냥 순수한 동물 그 자체'를 그릴 수는 없을 거예요. '동물'은 개념적인 이름일 뿐, 실제로 존재하려면 '짖는다'거나 '운다' 같은 구체적인 동작이 정의되어야 하거든요.

안 만드는 게 아니라 '못' 만드는 이유 (기술적 관점)

  • 구현되지 않은 기능(Method) : 추상 클래스 안에는 "이 기능은 나중에 자식 클래스가 알아서 만들어!"라고 비워둔 추상 메서드가 포함되어 있는 경우가 많아요.
  • 논리적 오류 방지 : 만약 울음소리()라는 기능이 비어있는 '동물' 객체를 만들었는데, 누군가 그 객체에게 "울어봐!"라고 시키면 컴퓨터는 어떻게 해야 할지 몰라 고장이 나겠죠?
  • 가이드라인 역할 : 추상 클래스는 "나를 상속받는 자식들은 반드시 이런 기능들을 갖춰야 해"라고 규칙을 정해주는 표준 가이드 역할을 하기 위해 존재합니다.

3. 한눈에 비교하기

구분 일반 클래스 추상 클래스
성격 완성된 설계도 미완성 가이드라인
객체 생성 가능 (바로 실체화 가능) 불가능 (단독 사용 불가)
목적 실제 데이터를 넣고 사용 상속을 통한 구조 잡기 & 기능 강제

 

요약하자면!
추상 클래스는 "이런 종류의 클래스라면 공통적으로 이런 게 필요해"라고 정의만 해둔 '개념'일 뿐이라서, 구체적인 내용이 채워진 '자식 클래스'를 통해서만 세상 밖(객체)으로 나올 수 있는 것이랍니다.

4. 객체지향 용어

  • 객체 : 데이터(속성) + 연산(메서드) → 캡슐화
  • 메서드 : 객체가 어떻게 동작하는지 규정. 속성의 값을 변경하는 것.
  • 클래스 : 동일한 속성, 공통의 행위, 객체의 타입.
  • 추상클래스 : 서브클래스들의 공통적인 특성을  하나의 슈퍼클래스로 추출(토끼, 사자, 호랑이 → 동물)
  • 다형성 :  동일 메시지에 대해 각 클래스가 가진 고유의 방법으로 응답
  • 상속성 : 상위 클래스의 속성과 메서드를 각자 자기 특성에 맞게 수정하여 사용
  • 캡슐화 : 객체 정의 시 서로 관련이 많은 테이터들과 연관된 함수들을 정보처리에 필요한 기능 하나로 묶음
  • 인스턴스 : 클래스 정의를 통해 만들어진 객체

5. 기출예제

<2021년 국가 7급>
다음 코드에서 오류가 발생하는 문장은?

 abstract class Shape {
	public void paint() { draw(); }
	abstract public void draw();
 }
 abstract class Circle extends Shape {
	 public int radius;
	 public Circle(int radius) { this.radius = radius; }
	 double getArea() { return (3.14 * radius * radius); }
 }
 public class NamedCircle extends Circle {
	 String name;
	 public NamedCircle(int radius, String name) {
		 super(radius);
		 this.name = name;
	 }
	 public void draw() { System.out.println("반지름이 " + radius + "인 원을 그리다."); }
	 public static void main(String[] args) {
		 Shape s;
		 s = new Shape(); // 오류발생. Shape는 추상클래스여서 객체를 생성할 수 없음.
		 NamedCircle w = new NamedCircle(5, "Ring");
		 System.out.println(w.getArea());
		 w.draw();
	 }
 }


< 2014년 국가 7급>

다음 클래스 정의에 따라 ㉠∼㉣ 문장을 수행할 때, 오류가 발생하지 않는 것만을 모두 고른 것은?

abstract class A { }
class B extends A { }
... 
A inst1 = new A(); // ㉠ 오류발생. 추상클래스 A는 객체를 생성할 수 없음
A inst2 = new B(); // ㉡ 정상실행. 부모(A)=자식(B)
B inst3 = new B(); // ㉢ 정상실행.
B inst4 = new A(); // ㉣ 오류발생. 자식(B)=부모(A)