추상클래스란?
추상클래스는 실체클래스의 공통적인 부분(변수,메서드)를 추출해서 선언한 클래스이다.
예를 들면 세상엔 많은 종류의 자전거(두발 자전거, 세발 자전거, 2인 자전거 등등...)가 있지만
그 모든 자전거에는 페달을 밟아 바퀴를 굴려 앞으로 나아가는 공통적인 메소드가 존재하고 이 부분만을 추출해 선언한 클래스라는 것이다.
추상적이고 구체적이지 않은 클래스인만큼 추상클래스는 객체를 직접 생성할 수 없다.
객체를 직접 생성할 수 있는 클래스를 실체클래스라고 하는데, 실체클래스들의 공통적인 특성을 추출해서 선언한 클래스를 추상클래스라고 한다. 여기서 추상클래스와 실체클래스는 상속적인 관계를 가지고 있다.
그렇다면 추상클래스는 왜 사용하는걸까?
첫 번째로, 공통된 필드와 메서드를 통일할 목적이다.
10명의 개발자에게 전자레인지를 상속받아 개발하라고 각자 자신만의 메소드와 변수를 통해 전자레인지를 구성해나갈 것이고 두 가지 제품이 선정되어 통일시켜야한다 했을 때 서로 다른 메소드와 변수를 맞추는 시간만 한 세월일 것이다.
이 때, 추상클래스에서 미리 정의한 필드와 메소드가 있다면, 실체클래스는 추상클래스의 필드와 메소드명을 변경할 수 없고 무조건 해당 명명으로 구현해야한다. 따라서, 필드와 메소드 이름을 통일하여 유지보수성을 높이고 통일성을 유지할 수 있다.
두 번째로, 실체클래스 구현시, 시간절약을 위해서
내가 전자레인지를 구현해야하는데, 전자레인지 추상클래스를 상속받으면, 자연스럽게 전자레인지 공통적으로 들어가야하는 필드와 메소드가 녹여져있는 필드와 메소드가 똭 하고 오버라이딩 된다.
즉, 상속되어 주어지는 필드와 메소드를 가지고 나만의 스타일대로 구현만 하면 된다.
다시 말해 필드와 메소드를 고민할 시간이 줄어드므로 설계 시간이 절약된다는 말이다.
세 번째로, 규격에 맞는 실체클래스 구현을 위해서
위에서 말한 것처럼 시간절약하면서 자신만의 스타일대로 구현할 수 있다고 했지만
이는, 결국 정해진 틀 안에서 주어진 자유이며 큰 틀은 강제적으로 지켜야한다는 것이다.
추상클래스를 상속받은 실체클래스들은 반드시 추상메소드를 오버라이딩해서 실행 내용을 작성해야 한다.
만약 그렇지 않으면 컴파일 에러를 발생시켜 실행조차 못하게 막기 때문이다.
따라서, 개발자들은 강제적으로 추상메소드를 구현해야한다.
여기서 추상메서드란, 추상클래스 안에 abstract 키워드를 가지고 있는 메소드는 추상메소드라고 하고,
상속시 반드시 재정의해야하는 메소드라는 뜻이다.
소스 수정시 다른 소스의 영향도를 적게 가져가면서 변화에는 유연하게 만들기 위해 추상클래스를 사용하기도 한다.
규격에 맞게 소스가 구현되어 있기 때문에 해당 규격에 대한 구현부만 수정하면 손 쉽게 수정이 가능하기 때문이다.
이제 실제 코드를 살펴보자.
클래스 앞에 abstract 키워드를 붙이면 추상클래스이다.
public abstract class 클래스명{
//필드
//생성자
//메서드
//추상메서드
}
class 앞에 abstract 키워드를 쓰는 것만으로 추상클래스를 만들 수 있다.
public abstract class GrandParent {
String name ;
int age ;
// 함수를 만드는데 함수를 이름만 만들자.
abstract void print();
abstract void test();
}
함수를 이름만 만들어 틀을 만들자. 구체적이지 않아도 되므로 괜찮다.
public abstract class Parent extends GrandParent{
// String name ;
// int age ;
@Override
void print() {
// TODO Auto-generated method stub
System.out.println("Parent");
System.out.println("name = " + name);
System.out.println("age = " + age);
}
// 추상클래스를 상속받아서 개발하는 클래스는
// 추상클래스의 모든 추상함수를 다 구현해주어야한다.
}
다음은 위 추상클래스를 상속받아 실체화시킨 실체 클래스이다.
메소드를 오버라이딩해 구현한 것이다.
이 때 추상클래스에서 정의한 모든 추상함수를 모두 다 구현해주어야만 오류없이 실행시킬 수 있는데
위 코드에선 다시 한 번 abstract 를 써주어서 구현되지 않은 메소드를
다른 실체 클래스에서 이어 정의할 수 있도록 다시 한 번 추상클래스로 만들어주었다.
public class Child extends Parent {
String hobby;
@Override
void test() {
// TODO Auto-generated method stub
System.out.println("Hobby = " + hobby);
}
}
앞선 코드에서 구현되지 않았던 메소드를 상속관계로 이어 받아 구현시켜주었다.
public class AbstractMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
Child c = new Child();
c.name = "홍길동";
c.age = 30;
c.hobby = "영화";
c.print();
c.test();
}
}
main 함수로 확인해보자.
코드가 정상적으로 작동되었다!
'JAVA' 카테고리의 다른 글
JAVA - ArrayList 사용법 (0) | 2022.07.06 |
---|---|
JAVA - 인터페이스(Interface)를 사용하는 이유와 사용방법 (0) | 2022.07.06 |
JAVA - 상속관계의 클래스에 대한 캐스팅 - 업캐스팅(UpCasting) (0) | 2022.07.05 |
JAVA - 부모 생성자 호출을 위한 super 키워드 사용법 (0) | 2022.07.05 |
JAVA - 메소드 오버라이딩(Method Overliding)에 대해 / super 키워드 (0) | 2022.07.04 |
댓글