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