본문 바로가기

JAVA

추상 클래스 (Abstract class)

1.  추상 클래스란?

 

기존의 클래스는 객체를 생성하기 위한 설계도로 비유할 수 있다면,

추상 클래스는 미완성 된 설계도라고 볼 수 있다.

 

여기서 미완성 되었다라는 것을 알 수 있는 부분은 메서드이다.

🖍 생성자나 변수로는 미완성 되었다는 것을 코드 상에서는 알 수 없다.

메서드가 미완성 되었다라는 것을 자바에서는 '추상 메서드'로 표현한다.

 

즉 추상 클래스는 abstract 키워드로 명시적 표현이 가능하고,

이로 인하여 기존의 구상 클래스와의 구분이 명확해진다.

abstract class 추상클래스 { 추상 메서드 }

구상 클래스는 완성된 설계도이기 때문에 해당 클래스를 통하여 인스턴스를 생성할 수 있지만,

추상 클래스는 미완성 설계도이기 때문에 인스턴스를 생성할 수 없다는 제약이 생긴다.

🖍 다만 인스턴스를 생성할 때 익명 클래스를 통하여 추상 메서드를 정의하면 인스턴스를 생성할 수도 있다.

 

또한 추상 클래스에는 추상 메서드 뿐만 아니라 구상 메서드도 가질 수 있으며,

추상 메서드는 반드시 있어야 할 필요는 없지만, 만일 추상 메서드가 존재한다면 해당 클래스는 반드시 추상 클래스로 선언되어야 한다.

 

 

2. 클래스의 추상화

 

인스턴스를 생성할 수 없는데 그럼 추상 클래스는 어떻게 활용할 수 있을까?

 

이는 클래스의 추상화를 통하여 활용이 가능해진다.

 

추상화란 간단히 말해 '클래스 간의 공통점을 추출하여 이들 간의 관계를 지어주는 것'을 의미한다.

class Circle {
	
    // 반지름
    int r;
    
    // 넓이
    double area() {
    	return Math.PI * r * r;
    }
    
    // 둘레
    double  circumference() {
    	return Math.PI * 2* r;
    }
}

class Quadrangle {
	
    // 가로
    int x;
    // 세로
    int y;
    
    // 넓이
    double area() {
    	return x * y;
    }
    
    // 둘레
    double  circumference() {
    	return 2 * (x + y);
    }
}

원과 사각형 클래스가 있다고 가정하였을 때,

공통 부분을 추출하자면 넓이와 둘레 구하는 메서드가 존재한다는 점일 것이다.

 

이러한 부분을 추상 클래스로 만들어 본다면 다음과 같이 나타낼 수 있다.

abstract class Shape {
	
    abstract double area();
    abstract double circumference();
}

class Circle extends Shape {}

class Quadrangle extends Shape {}

 

추상 클래스는 추상 메서드는 물론 구상 메서드 또한 가질 수 있지만,

해당 메서드를 상속받아 각각의 구현부가 다르다면 이렇게 추상 메서드로 선언하는 것이 좋다.

 

이렇게 구현하게 되면 Shape는 인스턴스를 생성하지 못하기 때문에 직접적인 활용은 할 수 없지만

상속을 통하여 원과 사각형 클래스의 인스턴스로 인하여 간접적인 활용이 가능해진다.

 

추상 클래스는 이렇듯 직접 인스턴스로 구현하지 않아도 되는 클래스를 지정하는 것이 좋고,

추상 메서드는 자식 클래스에서 별도의 구현이 지속적으로 필요하지만

모든 자식 클래스가 일정한 패턴으로 활용되는 것을 강요하고 싶다면 추상 메서드로 선언하는 것이 좋다.

 

3. 추상 메서드

 

추상 메서드는 선언부를 작성해두고 구현부는 해당 클래스를 부모 클래스로 하는 자식 클래스에게 구현을 하도록 강제하는 메서드이다.

선언부를 이미 작성해 놓았기 때문에 선언부는 변경이 불가하며

이로 인하여 자식 클래스에서는 구현부의 내용만 다를 뿐, 메서드의 형태는 일정해진다는 특징을 갖게 된다.

 

추상 클래스는 이러한 추상 메서드의 존재 가능성으로 인하여 미완성 설계도가 되는 것이다.

 

추상 메서드의 형태는 다음과 같다.

abstract 리턴타입 메서드이름 ();

구현부는 자식 클래스에서 구현하기 때문에 구현하는 블록 또한 명시하지 않는다.

 

그렇다면 어떠한 경우에 어떠한 메서드를 사용하는 것이 좋을까?

자식 클래스 모두 다른 구현을 해야 할 때 ➡️ 추상 메서드
몇몇 개의 자식 클래스에서만 다른 구현을 해야 할 때 ➡️ 구상 메서드 (다른 구현을 해야 하는 경우에는 오버라이드)
특정 자식 클래스군에서만 구현해야 할 때 ➡️ 인터페이스의 디폴트 메서드

대략 이러한 경우를 염두하여 메서드를 어떻게 구현할지 고민할 수 있다.

'JAVA' 카테고리의 다른 글

내부 클래스와 익명 클래스  (0) 2022.09.26
인터페이스  (1) 2022.09.26
여러 타입의 객체를 하나의 배열로 다루기  (1) 2022.09.25
다형성  (0) 2022.09.24
this 와 super  (0) 2022.09.21