추상 클래스의 의미
- 실체들의 공통되는 특성을 가지고 있는 클래스를 의미하며 규격(기준) 클래스라고도 부른다.
- 실체 클래스(자식)와 추상클래스(부모)는 상속의 관계를 가지고 있음
- 실체 클래스는 추상 클래스의 모든 특성(필드, 메소드)을 물려받고 추가로 다른 특성을 가질 수 있음
- Dog 클래스와 Cat 클래스에서 공통으로 사용된 필드나 메소드를 따로 Animal 클래스에다가 만들 수 있음
추상 클래스를 사용하는 목적 2가지
1. 시간 절약
- 집전화기와 스마트폰 모두 사용자라는 데이터와 전원이라는 기능이 필요한데 이를 각각에 만들어주면 일이 2배로 늘어나게된다.
- 따라서 전화 라는 추상 클래스를 만들어 거기에 사용자와 전원을 만들어주면 그걸 불러쓰면 되기 때문에 일이 수월해진다.
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("폰 전원을 끕니다.");
}
}
SmartPhone 클래스 (실체 클래스)
public class SmartPhone extends Phone{
// 생성자
public SmartPhone(String owner) {
super(owner); // Phone의 생성자를 호출
}
// 메소드
public void internetSearch() {
System.out.println("인터넷 검색을 합니다.");
}
}
PhoneExample 클래스 (실행 클래스)
public class PhoneExample {
public static void main(String[] args) {
// Phone phone = new Phone(); // 추상클래스의 객체를 new로 생성할 수 없음
SmartPhone smartPhone = new SmartPhone("홍길동"); // 대신 자식 클래스로 객체를 생성해서
smartPhone.turnOn(); // 추상 클래스의 메소드들을 사용할 수 있다.
smartPhone.internetSearch();
smartPhone.turnOff();
}
}
출력 결과
폰 전원을 켭니다.
인터넷 검색을 합니다.
폰 전원을 끕니다.
추상 메소드
- 실체 클래스들의 메소드 이름과 기능은 동일하지만 각 기능마다 조금씩 다르게 작성하고 싶을 때
- 실체 클래스에서 추상 메소드를 재정의하여 실행 내용을 꼭 작성하도록 하는 메소드이다.
- 특징 : 메소드 리턴타입 앞에 abstract 를 붙여 쓰면 된다.
- 이 경우 실체 클래스에서 오버라이딩 하지 않는 경우 컴파일 에러를 발생시킨다.
- 하위 클래스에서 반드시 실행 내용을 쓰도록 하고 싶은 메소드가 있다면 추상 메소드로 선언한다.
예 ) 모든 동물은 소리(추상 메소드)를 낸다. 하지만 전부 다른 소리(추상 메소드 재정의)를 낸다.
- 형태
public(protected) abstract 리턴타입 메소드명(매개변수)
추상 메소드 예제
Animal 클래스 (추상 클래스)
public abstract class Animal { // 추상(규격) 클래스
// 필드
public String kind;
// 메소드
public void breathe() {
System.out.println("숨을 쉽니다.");
}
// 추상 메소드(상속받는 자식 클래스에서의 오버라이딩을 강제화)
public abstract void sound();
}
Cat 클래스 (실체 클래스)
public class Cat extends Animal{
// 생성자
public Cat() {
this.kind = "포유류";
}
@Override // 추상 메소드 재정의
public void sound() {
System.out.println("야옹");
}
}
Dog 클래스 (실체 클래스)
public class Dog extends Animal {
// 생성자
Dog() {
this.kind = "포유류";
}
@Override // 추상 메소드 재정의
public void sound() {
System.out.println("멍멍");
}
}
AnimalExample 클래스 (실행 클래스)
public class AnimalExample {
public static void main(String[] args) {
// 방법 1. 변수로 호출
Dog dog = new Dog();
Cat cat = new Cat();
dog.sound();
cat.sound();
System.out.println("----------");
// 방법 2. Animal 타입 변수로 자동 타입 변환
Animal animal = null;
animal = new Dog();
animal.sound();
animal = new Cat();
animal.sound();
System.out.println("----------");
방법 3. 부모 타입의 매개 변수 animal에 자식 객체(new Dog())를 대입
animalSound(new Dog());
animalSound(new Cat());
}
public static void animalSound(Animal animal) {
animal.sound();
}
}
위 예제의 sound() 메소드를 호출하는 세 가지 방법 설명
방법 1. Dog 변수와 Cat 변수로 호출
방법 2. Animal 변수로 타입 변환을 통해 호출 (Animal 타입의 animal 변수에 Dog(자식) 객체를 선언해주면 Animal(부모) 객체로 자동 타입 변환이 된다.
메소드가 재정의되어있는 경우라면 여기서 animal은 자식 객체가 들어있는 변수이므로 자식 메소드가 호출된다.
(다형성의 특징임)
방법 3. 부모 타입의 매개 변수 animal에 자식 객체(new Dog())를 대입하여 메소드의 다형성을 적용한다.
(방법 2와 같은 원리로서 자식 객체가 부모 타입으로 자동 타입 변환되어 재정의된 sound() 메소드가 호출됨)
'👨🏫Study > JAVA' 카테고리의 다른 글
[JAVA] 08 - 2 타입 변환과 다형성 (0) | 2022.03.21 |
---|---|
[JAVA] 08 - 1 인터페이스 (0) | 2022.03.21 |
[JAVA] 07 - 2 타입 변환과 다형성 (0) | 2022.03.21 |
[JAVA] 07 - 1 상속 (0) | 2021.08.11 |
[JAVA] 06 - 6 패키지와 접근 제한자 (0) | 2021.08.06 |
댓글