- 미완성 메소드(추상 메소드)를 보유하고 있는 클래스
- (추상 메소드는 없지만) 객체로 만들면 안 되는 클래스
[접근제한자] abstract class 클래스명 {}
미완성 메소드
[접근제한자] abstract 반환형 메소드명(자료형 변수명);
package edu.kh.poly.ex2.model.vo;
public abstract class Animal {
// 추상 클래스(abstract class)
// 필드
private String type; // 종/과 구분
private String eatType; // 식성(초식, 육식, 잡식)
// 생성자
// - 추상 클래스는 new 연산자를 이용해서 직접적인 객체 생성은 불가능하지만
// 상속받은 객체 생성 시 부모 부분이 생성될 때 사용된다.
// == super() 생성자
public Animal() {
super(); // 생략 시 컴파일러가 추가
} // 기본 생성자
public Animal(String type, String eatType) { // 매개변수 생성자 (오버로딩 적용)
this.type = type;
this.eatType = eatType;
}
// 메소드
// getter / setter
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getEatType() {
return eatType;
}
public void setEatType(String eatType) {
this.eatType = eatType;
}
// toString() 오버라이딩
@Override // 오버라이딩 되었음을 컴파일러에게 알려 주는 어노테이션
public String toString() {
return type + " / " + eatType;
}
// 동물의 공통 기능 추출(추상화)
// -> 동물은 공통적으로 먹고, 숨쉬지만
// 어떤 동물이냐에 따라 그 방법이 다름!
// --> 그럼 어떡할까?
// 미완성 상태로 두어 상속받은 자식이 해당 메소드를 정의하도록
// 오버라이딩을 강제화시킴 --> 추상(abstract) 메소드로 작성
// 먹다
public abstract void eat();
// 숨쉬다
public abstract void breath();
}
package edu.kh.poly.ex2.model.vo;
public class Person extends Animal{
// Animal의 추상 메소드를 오버라이딩 하지 않으면 오류 발생
private String name;
// 생성자
public Person() { // 기본 생성자
super(); // == Animal의 기본 생성자
}
public Person(String type, String eatType, String name) { // 매개변수 생성자
super(type, eatType);
this.name = name;
}
// getter / setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void eat() {
System.out.println("숟가락, 젓가락, 나이프, 포크 등을 이용해서 먹는다.");
}
@Override
public void breath() {
System.out.println("코와 입으로 숨을 쉰다.");
}
// toString()
@Override
public String toString() {
return "Person : " + super.toString() + name;
}
}
package edu.kh.poly.ex2.model.vo;
public class Fish extends Animal{
// 생성자
// -> 생성자 미작성 시 컴파일러가 자동으로 기본 생성자를 추가해 줌
public Fish() {
super();
}
public Fish(String type, String eatType) {
super(type, eatType);
}
// 추상 메소드는 상속받으면 오버라이딩이 강제된다.
@Override
public void eat() {
System.out.println("입을 뻐끔 뻐끔 거리면서 먹는다.");
}
@Override
public void breath() {
System.out.println("아가미 호흡을 한다.");
}
// toString()
@Override
public String toString() {
return "Fish : " + super.toString();
}
}
package edu.kh.poly.ex2.model.service;
import edu.kh.poly.ex2.model.vo.Animal;
import edu.kh.poly.ex2.model.vo.Fish;
import edu.kh.poly.ex2.model.vo.Person;
public class AbstractService {
public void ex1() {
// 추상 클래스는 객체로 만들 수 있을까? (X)
// Animal a1 = new Animal();
// Cannot instantiate the type Animal (객체화 할 수 없다)
// 클래스 : 객체의 속성, 기능을 정의한 것 (일종의 설계도)
// 추상 클래스 : 미완성 메소드를 포함한 클래스 (미완성 설계도)
// -> 미완성 설계도로는 객체를 만들 수 없다!! -> 오류 발생
// 해결 방법 : Animal을 상속받아 미완성 부분을 구현한 클래스를 이용해 객체 생성
// * 추상 클래스를 상속받은 자식 객체 생성하기
Person p1 = new Person();
p1.setName("공유");
// 상속 받은 기능 호출
p1.setType("척추동물");
p1.setEatType("잡식");
// 오버라이딩한 메소드 호출
p1.eat();
p1.breath();
Fish f1 = new Fish();
f1.eat();
f1.breath();
}
public void ex2() {
// * 추상 클래스와 다형성 + 바인딩
// - 추상 클래스는 객체로 만들 수 없다.
// ---> 하지만 "참조 변수"로는 사용할 수 있다.
// ex) 동물 -> 사람? 물고기?
// Animal a1 = new Animal(); (X)
// 사람 -> 동물 / 물고기 -> 동물
// Animal a1 = new Person(); Animal a2 = new Fish();
Animal[] arr = new Animal[2];
// Animal 참조 변수 배열 선언 및 할당
arr[0] = new Person("사람", "잡식", "김사랑");
// Animal 부모 = Person 자식 (다형성 중 업캐스팅)
arr[1] = new Fish("물고기", "잡식");
// Animal 부모 = Fish 자식 (다형성 중 업캐스팅)
// 바인딩 확인
for(int i=0; i<arr.length; i++) {
// arr[i] == Animal 참조 변수
arr[i].eat();
arr[i].breath();
System.out.println(arr[i]);
// void edu.kh.poly.ex2.model.vo.Animal.eat() - 정적 바인딩
// 프로그램 실행 시
// 참조하고 있는 자식 객체의 오버라이딩 된 eat() 메소드 수행
// - 동적 바인딩
// (부모 타입 참조 변수로 메소드를 호출했지만
// 자식 타입에 오버라이딩된 메소드가 수행된다)
// 업캐스팅 상태(부모 참조 = 자식 객체)에서
// 부모 메소드 호출 시, 오버라이딩된 자식 메소드 수행
System.out.println("-----------------------------");
}
}
}