[Java 19] 자바 - 추상 클래스

학습목표

  1. 추상 클래스의 의미와 용도를 알고 있다.
  2. 추상 클래스의 선언과 오버라이딩을 이해하고 있다.

추상 클래스

추상(abstract)은 실체 간에 공통되는 특성을 추출한 것을 의미합니다. 객체를 직접 생성할 수 있는 클래스를 실체 클래스라고 한다면 클래스들의 공통적인 특성을 추출해서 선언한 클래스를 추상 클래스라고 합니다. abstract 클래스나 메소드를 사용하기 위해서는 반드시 상속해서 사용하도록 강제하는 것이 바로 abstract입니다.

추상 클래스는 실체 클래스의 공통되는 필드와 메소드를 추출해서 만들었기 때문에 객체를 직접 생성해서 사용할 수 없습니다. 즉, 추상 클래스는 new 연산자를 사용해서 인스턴스를 생성시키지 못한다는 것입니다.

Animal animal = new Animal(); // 불가능


추상 클래스의 용도

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

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


추상 클래스 선언

추상 클래스는 다음과 같이 선언합니다.

public abstract class 클래스 (
  //필드
  //생성자
  //메소드
)

추상 클래스도 일반 클래스와 마찬가지로 필드, 생성자, 메소드 선언이 가능합니다. new 연산자로 직접 생성자를 호출할 수는 없지만 자식 객체가 생성될 때 super(…)를 호출해서 추상 클래스 객체를 생성하므로 추상 클래스도 생성자가 반드시 있어야 합니다.

예제

[Phone] 추상 클래스

public abstract class Phone {
  //필드
	public String owner;
  //생성자
	public Phone(String owner) {
		this.owner = owner;
	}
  //메소드
	public void turnOn() {
		System.out.println("폰 전원을 켭니다.");
	}

	public void turnOff() {
		System.out.println("폰 전원을 끕니다.");
	}
}

[SamrtPhone] 실체 클래스

public class SmartPhone extends Phone {
  //생성자
	public SmartPhone(String owner) {
		super(owner);
	}
  //메소드
	public void internetSearch() {
		System.out.println("인터넷 검색을 시작합니다.");
	}
}

[PhoneMain]

public class PhoneMain {
	public static void main(String[] args) {
    //Phone phone = new Phone(); //Phone의 생성자 호출해서 사용불가
		SmartPhone sp = new SmartPhone("홍길동");
		
		sp.turnOn();
		sp.internetSearch();
		sp.turnOff();
	}
}


추상 메소드와 오버라이딩

모든 실체들이 가지고 있는 메소드의 실행 내용이 동일하다면 추상 클래스에 메소드를 작성하는 것이 좋을 것입니다. 그러나 메소드의 선언만 통일화하고, 실행 내용은 실체 클래스마다 달라야 하는 경우가 있습니다. 이런 경우 추상 클래스는 추상 메소드를 선언할 수 있습니다. 추상 메소드는 추상 클래스에서만 선언할 수 있는데, 메소드의 선언부만 있고 메소드 실행 내용인 중괄로 {}가 없는 메소드를 말합니다.

추상 클래스를 설계할 때, 하위 클래스가 반드시 실행 내용을 채우도록 강요하고 싶은 메소드가 있을 경우, 해당 메소드를 추상 메소드로 선언하면 됩니다. 그러면 자식 클래스는 반드시 추상 메소드를 재정의(오버라이딩)해서 실행 내용을 작성해야 하고, 그렇지 않으면 컴파일 에러가 발생합니다.

[ public | protected ] abstract 리턴타입 메소드명(매개변수, ...);

예제

Animal 클래스를 추상 클래스로 선언하고 sound() 메소드를 추상 메소드로 선언한 예제이다.

public abstract class Animal {  //Animal을 추상 클래스로 선언
  public abstract void sound();   // sound() 메소드를 추상 메소드로 선언
}

[Animal] 추상 클래스

public abstract class Animal {
	public String kind;
	
	public void breath() {
		System.out.println("숨을 쉽니다.");
	}
	
	public abstract void sound();
	}

[Dog] 추상 메소드 오버라이딩

public class Dog extends Animal {
	public Dog() {
		this.kind = "포유류";
	}
	
	@Override
	public void sound() {
		System.out.println("멍멍");
	}
}

[Cat] 추상 메소드 오버라이딩

public class Cat extends Animal {
	public Cat() {
		this.kind = "포유류";
	}
	
	@Override
	public void sound() {
		System.out.println("야옹");
	}
}

[AnimalMain]

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

		dog.sound();
		dog.breath();
		cat.sound();
		cat.breath();
		System.out.println("--------");

		Animal animal = null;
		animal = new Dog();
		animal.sound();

		animal = new Cat();
		animal.sound();
		System.out.println("--------");
	}
}

실행결과

멍멍
숨을 쉽니다.
야옹
숨을 쉽니다.
--------
멍멍
야옹
--------

태그:

카테고리:

업데이트:

댓글남기기