추상 클래스의 용도

 

1. 실체 클래스*1 들 간 비슷한 공통점을 가진 필드과 메소드들의 이름을 통일할 목적

 : 여러 사람이 실체 클래스를 설계하는 경우, 실체 클래스마다 필드와 메소드가 각각 다른 이름을 가질 수 있다. 이를 방지하기 위해 추상 클래스*2 에서 필드와 메소드의 이름을 정하고, 이를 상속받음으로써 공통된 필드와 메소드를 통일할 수 있다.

*1 실체 클래스 실체 클래스라 함은 실제 객체를 생성할 수 있을 정도의 구체성을 가진 클래스
개념적으로 보자면, "클래스" 는 객체(object)를 구현하기 위한 설계도. 실체 클래스는 결국 object를 구현할 수 있도록 매우 구체적으로 작성된 클래스를 의미한다.
자동차라는 객체를 설계한다고 하면, 기종의 이름은 000 / 차의 연료는 000 / 과 같이 매우 구체성을 담고 있는 클래스를 의미한다. 
*2 추상 클래스 위의 개념과 반대된다고 생각하면 된다. 즉 클래스이지만, 구체성이 없는 추상적인 의미만을 가진 클래스이다. 따라서 추상 클래스는 단일로 존재할 수 없다. 추상 클래스만으로 객체를 완성시킬 수는 없다.
따라서 추상 클래스는 실체 클래스를 자식 클래스로써 삼고, 실체 클래스는 추상 클래스를 오버라이딩 하며 실체성 있는 클래스를, 객체를 생성한다.

ex) '핸드폰' 이라는 객체, 클래스가 있다고 가정하자.

그러면 핸드폰에도 삼성이 만드는 갤럭시, 애플이 만드는 아이폰 등 여러 종류의 제품이 출시될 것이다.

하지만 어느 회사에서 만드는 핸드폰이라 할 지라도 공통적으로 지니고 있는 특징이 있다.

 

공통적으로 가지고 있는 부분, 공통되는 변수에는 화면, 배터리, 메모리칩 등등이 있을 것이다.

그리고 핸드폰을 "제조" 한다 라는 액션을 각 회사가 공통적으로 실시한다.

그 결과, 삼성도 애플도 배터리, 화면, 메모리칩을 사용하겠지만

삼성은 6인치의 큰 화면, 4000 용량의 배터리, 스냅드래곤의 메모리칩을 사용할 것이다.

애플은 5인치의 작은 화면, 3000 용량의 배터리, m1 의 메모리칩을 사용할 것이다.

 

삼성/애플 은 핸드폰이라는 객체를 상속받아서 자신만의 특징을 구체화시킨 실체 클래스인 것이다.

 

 

2. 실체 클래스를 작성할 떄 시간을 절약한다.

 : 공통되는 필드와 메소드는 추상 클래스에 모두 선언해두고, 실체 클래스마다 다른 점만 실체 클래스에 선언한다면 실체 클래스를 작성하는데 시간을 절약할 수 있을 것이다.

 

예를 들어보자.

만약 다음 시즌에 출시할 '아이폰' 이라는 클래스를 개발하라는 의뢰가 들어왔다.

그런데 매 번 화면이 있어야 하고... 배터리가 필요하고... 메모리칩을 넣어야 하고... 이와 같이 필요한 부분들을

하나하나 설계해나가는 것에는 매우 많은 시간이 소모된다.

 

그런데 이미 만들어진 '아이폰' 이라는 상위 추상 클래스를 오버라이딩하여서,

화면 사이즈만 구체화하고, 배터리 용량만 구체화한다면 시간이 훨씬 단축될 것이다.

 

 

이미지적으로 기억하기에는 아래가 가장 쉬울 수 있다.

출처 : https://limkydev.tistory.com/188

 

추상 클래스 문법체계

public abstract class AbstractClass{
        // 필드
        // 생성자
        // 메소드
        public abstract void abstractMethod();
        // 추상 메소드 : 중괄호 안에는 입력하지 않는다.
}

 

실제로 추상 클래스 예시로 자주 등장하는 Animal 메소드로 구현해보고자 한다.

public abstract class Animal {
    // 동물의 종류 구현
    public String kind;
    public String name;

    public void breath(){
        System.out.println("숨 쉰다.");
    }
    //추상 메소드
    public abstract void sound();
}

Animal 이라는 추상 클래스를 생성했다. 그 후 sound() 라고 이름 붙인 추상 메소드를 만들었다.

추상 메소드는 중괄호 안의 값이 없다.

 

public class Dog extends Animal {

    public Dog(){
        this.kind = "포유류";
        this.name = "강아지";
    }
    @Override
    public void sound() {
        System.out.println("왈왈");
    }
}

Animal을 extends 상속하는 Dog 라는 이름의 클래스를 생성했다.

Dog 는 Animal 추상 클래스를 상속받아 구체화 시키는 실체 클래스이다.

Animal 의 추상 메소드였던 sound() 를 오버라이딩 한 후,

"왈왈" 이라는 문자열이 출력되도록 수정하였다.

 

public class Cat extends Animal {

    public Cat(){ // 생성자!!!
        this.kind = "포유류";
        this.name = "고양이";
    }
    @Override
    public void sound(){
        System.out.println("야옹");
    }
}

Animal을 extends 상속하는 Cat 라는 이름의 클래스를 생성했다.

Cat 는 Animal 추상 클래스를 상속받아 구체화 시키는 실체 클래스이다.

Animal 의 추상 메소드였던 sound() 를 오버라이딩 한 후,

"야옹" 이라는 문자열이 출력되도록 수정하였다.

 

public class AnimalExample {
    public static void main(String[] args) {
        Dog d = new Dog();
        Cat c = new Cat();
        System.out.println(d.name);
        d.sound();
        d.breath();
        System.out.println(c.name);
        c.sound();
        c.breath();
        System.out.println("--------------");
        Animal animal = null; // Animal 이라는 객체를 animal 이라는 이름으로 생성.
        animal = new Dog();
        System.out.println(animal.name);
        animal.sound();
        animal.breath();

        animal = new Cat();
        System.out.println(animal.name);
        animal.sound();
        animal.breath();

    }
}
강아지
왈왈
숨을 쉰다.
고양이
야옹
숨을 쉰다.
--------------
강아지
왈왈
숨을 쉰다.
고양이
야옹
숨을 쉰다.

 

 

* 추상 메소드가 필요한 이유

 

모든 실체들(Dog, Cat 과 같은)이 가지고 있는 메소드의 실행내용이 동일하다면, 추상 클래스 하나에 메소드를 기입하는 것이 가장 효율적이다. 

public abstract Animal{
	public String kind;
    
    public void kinds(){
    	System.out.println("포유류"}
}

만약 Animal 추상 클래스에 "포유류" 라는 것을 출력하는 메소드를 만들었다. dog와 cat 는 모두 포유류이기 때문에 이 메소드가 작동되어도 상관이 없지만 독수리라는 새로운 실체 클래스가 만들어진다면 어떨까?

독수리.kinds() 를 출력하게 되면 똑같이 포유류가 나올 것이다. 이건 정답이 아니다.

 

따라서 각각의 실체 클래스마다 특성을 담기 위해서 추상 메소드가 등장했다.

추상 메소드는 메소드명만 있을 뿐, 어떻게 출력될 지에 대해서는 정의되어 있지 않다.

위의 public abstract void sound(); 와 같은 메소드가 추상 메소드이다.

dog 실체 클래스에서는

@Override

public void sound(){

   System.out.println("왈왈")

}

과 같이 sound() 메소드를 이름만 가져온 채 dog 만의 특징을 담은 것이다.

 

 

 

 

 

 

참조

https://limkydev.tistory.com/188

https://hyuntaekhong.github.io/blog/java-basic19/

BELATED ARTICLES

more