처음부터 차근차근

[Java] abstract 추상 클래스 & 추상 메서드 본문

Language/Java

[Java] abstract 추상 클래스 & 추상 메서드

HangJu_95 2024. 1. 2. 15:02
728x90

추상이란??

여러 가지 사물이나 개념에서 공통되는 특성이나 속성 따위를 추출하여 파악하는 작용.

 

즉, 추상화란 '형상을 뽑아내어 변화시키는 것'이라고 정의할 수 있습니다.

고양이, 강아지, 소에서 추상을 하면 동물, 포유류 등을 추상화 할 수 있습니다.

쉽게 말하자면 '일반화' 같은 것입니다.

추상 클래스

클래스를 설계도에 비유한다면, 추상 클래스는 미완성 설계도라고 비유할 수 있습니다.

추상 클래스는 이름 그대로 추상적인 개념을 제공하는 클래스입니다. 따라서 실체인 인스턴스가 존재하지 않습니다.

대신에, 상속을 목적으로 사용되고 부모 클래스 역할을 맡는 중요한 의미를 갖습니다.

abstract class AbstractAnimal {...}
  • 추상 클래스는 클래스를 선언할 때 앞에 추상이라는 의미의 abstract키워드를 붙여주면 된다.
  • 추상 클래스는 기존 클래스와 완전히 같다. 다만 new AbstractAnimal() 와 같이 직접 인스턴스를 생성하지 못하는 제약이 추가된 것이다.
  • 여러 클래스에 공통적으로 사용될 수 있는 클래스를 바로 작성하기도 하고, 기존의 클래스의 공통적인 부분을 뽑아서 추상클래스로 만들어 상속하는 경우도 존재합니다.

추상 메서드

메서드 중 선언부만 작성하고 구현부는 작성하지 않은 채로 남겨둔 것이 추상 메서드입니다.

부모 클래스를 상속 받는 자식 클래스가 반드시 오버라이딩 해야하는 메서드를 정의할 수 있습니다. 이것을 추상 메서드로 강제할 수 있습니다.

public abstract void sound();
  • 추상 메서드는 선언할 때 메서드 앞에 추상이라는 의미의 abstract 키워드를 붙여주면 된다.
  • 추상 메서드가 하나라도 있는 클래스는 추상 클래스로 선언해야 한다.
    • 그렇지 않으면 컴파일 오류가 발생한다.
    • 추상 메서드는 메서드 바디가 없다. 따라서 작동하지 않는 메서드를 가진 불완전한 클래스로 볼 수 있다. 따라서 직접 생성하지 못하도록 추상 클래스로 선언해야 한다.
  • 추상 메서드는 상속 받는 자식 클래스가 반드시 오버라이딩 해서 사용해야 한다.
    • 그렇지 않으면 컴파일 오류가 발생한다.
    • 추상 메서드는 자식 클래스가 반드시 오버라이딩 해야 하기 때문에 메서드 바디 부분이 없다. 바디 부분을 만들면 컴파일 오류가 발생한다.
    • 오버라이딩 하지 않으면 자식도 추상 클래스가 되어야 한다.
  • 추상 메서드는 기존 메서드와 완전히 같다. 다만 메서드 바디가 없고, 자식 클래스가 해당 메서드를 반드시 오버라이딩 해야 한다는 제약이 추가된 것이다.

추상 클래스 예제

저번 시간에 활용했던 동물을 추상 클래스로 만들어보고 상속시켜보겠습니다.

package poly.ex3;

public abstract class AbstractAnimal {
    public abstract void sound();

    public void move() {
        System.out.println("동물이 움직입니다.");
    }
}
package poly.ex3;

public class Cat extends AbstractAnimal {
    @Override
    public void sound() {
        System.out.println("냐옹");
    }
}
package poly.ex3;

public class Caw extends AbstractAnimal {
    @Override
    public void sound() {
        System.out.println("음매");
    }
}
package poly.ex3;

public class Dog extends AbstractAnimal {
    @Override
    public void sound() {
        System.out.println("멍멍");
    }
}
package poly.ex3;

public class AbstractMain {
    public static void main(String[] args) {
        //추상클래스 생성 불가
//        AbstractAnimal animal = new AbstractAnimal();
        Dog dog = new Dog();
        Cat cat = new Cat();
        Caw caw = new Caw();
        cat.sound();
        cat.move();
        soundAnimal(cat);
        soundAnimal(dog);
        soundAnimal(caw);
    }
    //동물이 추가 되어도 변하지 않는 코드
    private static void soundAnimal(AbstractAnimal animal) {
        System.out.println("동물 소리 테스트 시작");
        animal.sound();
        System.out.println("동물 소리 테스트 종료");
    }
}
  • 추상 클래스는 생성이 불가능합니다. 만약 생성할려고 한다면 컴파일 오류가 발생합니다.
  • 추상 메서드는 반드시 오버라이딩을 해야 합니다. 지키지 않는다면 컴파일 오류가 발생합니다.

  • 위의 두 가지 제약을 제외한다면 나머지는 모두 일반적인 클래스와 동일합니다.

순수 추상 클래스

모든 메서드가 추상 메서드인 추상 클래스를 순수 추상 클래스라고 합니다.

순수 추상 클래스는 코드를 실행한 바디 부분이 전혀 없습니다. 단지 다형성을 위한 부모 타입으로써 껍데기 역할만 제공할 뿐입니다.

순수 추상 클래스는 다음과 같은 특징을 가지고 있습니다.

  • 인스턴스를 생성할 수 없다.
  • 상속 시 자식은 모든 메서드를 오버라이딩 해야 한다.
  • 주로 다형성을 위해 사용됩니다.
package poly.ex4;

public abstract class AbstractAnimal {
    public abstract void sound();
    public abstract void move();
}
package poly.ex4;

public class Cat extends AbstractAnimal {
    @Override
    public void sound() {
        System.out.println("냐옹");
    }

    @Override
    public void move() {
        System.out.println("고양이 이동");
    }
}
package poly.ex4;

public class Caw extends AbstractAnimal {
    @Override
    public void sound() {
        System.out.println("음메");
    }

    @Override
    public void move() {
        System.out.println("소 이동");
    }
}
package poly.ex4;

public class Dog extends AbstractAnimal {
    @Override
    public void sound() {
        System.out.println("멍멍");
    }

    @Override
    public void move() {
        System.out.println("개 이동");
    }
}
package poly.ex4;

public class AbstrictMain {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Cat cat = new Cat();
        Caw caw = new Caw();

        soundAnimal(cat);
        soundAnimal(dog);
        soundAnimal(caw);

        moveAnimal(cat);
        moveAnimal(dog);
        moveAnimal(caw);
    }
    //동물이 추가 되어도 변하지 않는 코드
    private static void soundAnimal(AbstractAnimal animal) {
        System.out.println("동물 소리 테스트 시작");
        animal.sound();
        System.out.println("동물 소리 테스트 종료");
    }
    //동물이 추가 되어도 변하지 않는 코드
    private static void moveAnimal(AbstractAnimal animal) {
        System.out.println("동물 이동 테스트 시작");
        animal.move();
        System.out.println("동물 이동 테스트 종료");
    }
}

상속하는 클래스는 모든 메서드를 구현해야 하는 특징은 상속 받는 클래스 입장에서 보면 부모의 모든 메서드를 구현해야 합니다.

이런 특징을 잘 생각해보면 순수 추상 클래스는 마치 어떤 규격을 지켜서 구현해야 하는 것 처럼 느껴집니다.

 

이것은 우리가 일반적으로 이야기하는 인터페이스와 같이 느껴집니다. (USB 인터페이스에는 규격이 존재하고, 이 규격에 맞추어 제품을 개발해야 연결이 된다.)

 

이런 순수 추상 클래스의 개념은 프로그래밍에서 매우 자주 사용됩니다. 자바는 인터페이스라는 개념을 제공함으로써 순수 추상 클래스를 더 편리하게 사용할 수 있도록 인터페이스라는 개념을 제공합니다.

참조

자바의 정석_기초편

 

김영한의 실전 자바 - 기본편 강의 - 인프런

실무에 필요한 자바 객체 지향의 핵심 개념을 예제 코드를 통해 쉽게 학습합니다., 국내 개발 분야 누적 수강생 1위, 제대로 만든 김영한의 실전 자바[사진][임베딩 영상]단순히 자바 문법을 안다

www.inflearn.com

 

'Language > Java' 카테고리의 다른 글

[Java] Interface  (1) 2024.01.02
[Java] 다형성  (0) 2024.01.01
[Java] final  (1) 2023.12.31
[Java] static  (2) 2023.12.29
[Java] Java 메모리 구조  (1) 2023.12.29