JAVA 이클립스 추상 클래스(abstract class)
▣ 추상 클래스(abstract class)
- class
. (일반)클래스 : 객체 생성 가능
. 추상 클래스 : 객체 생성 할 수 없음
- 인터페이스(interface) : 객체 생성할 수 없음
1. 추상 클래스(abstract class)
- 추상메서드(abstract method)를 포함한 클래스
- 메서드의 본체가 정의되지 않은 미완성 메서드
abstract void showInfo(); => 추상
public void showInfo(){ => 일반 메서드
System.out.println("일반메서드");
}
- 추상클래스
abstract class Car{
abstract void showInfo();
public void printInfo(){
...
}
}
- 추상메서드를 하나도 포함하지 않아도 추상 클래스로 정의는 가능하다. 다만
추상메서드가 없는 경우 추상 메서드로 정의할 이유가 없다. 객체를 생성할 수 없기에
객체를 만드는 과정을 다시 거쳐야 함으로
2. 오버라이딩(overriding)과 구현하기(implements)
1) 오버라이딩 : 부모 클래스의 메서드(완성, 미완성)를 자식클래스에서 재정의(완성)
2) 구현하기(implements) : 부모 클래스의 미완성메서드(추상메서드)를 자식 클래스에서 재정의(완성)
- 오버라이딩 ------------------------------------------------------------------
| 부모클래스 완성메서드 -> 자식클래스 완성메서드 |
| |
| 구현하기 : |
| 부모클래스 미완성메서드 -> 자식클래스 완성메서드 |
| |
|-----------------------------------------------------------------|
* 메서드의 완성과 미완성의 구분 기준 : 중괄호의 존재 여부
중괄호 안에 아무런 코드가 없어도 완성된 메서드 => 아무일도 하지 말라고 명확히 기능이 표현된 메서드
3. 추상클래스의 필요성 :
- 아무것도 정의 되어있지 않은 일반메서드를 부모메서드에 만들고 자식이 상속을 받을 경우
자식은 재정의할 수도 있고 하지 않을 수도 있다. 자식이 재정의 하지 않아도 오류가 발생하지 않는다.
그러다 보면 재정의해서 사용해야 문제가 없는 것인데, 재정의하지 않아도 오류가 발생하지 않으므로
재정의를 놓치고 지나칠 수도 있어 크나큰 오류를 만들어 낼 수가 있다.( 자식이 반드시 오버라이딩 했다는 보장을 할 수 없음)
- 그러나 추상 메서드는 자식이 재정의하지 않으면 에러가 발생해서 반드시 재정의 해야 함으로 재정의를 빼놓는 실수를 하지 않게 됨
추상클래스는 자식 클래스가 반드시 재정의했다는 것을 보장할 수 있음.
abstract class Animal{
abstract void cry();
}
class Dog extends Animal{
@override
void cry(){
System.out.println("멍멍");
}
}
class Cat extends Animal{
@override
void cry(){
System.out.println("멍멍");
}
}
Animal aniDog = new Dog();
aniDog.cry(); //멍멍
Animal aniCat = new Cat();
aniCat.cry(); //야옹
4. 추상 클래스의 특징
- 추상클래스는 그 자체로는 객체 생성 불가하다. (추상메서드(미완성메서드)를 포함하기 때문
- heap 메모에 객체를 생성하기 위해서는 모두 완성된 메서드를 가질 때만 가능하다.
필드를 강제 초기화 (정수-0, float/double : 0.0,....)
heap메모리에 넣기 위해서는 반드시 완성된 것만 가능하다.
- 추상클래스는 클래스를 만드는 부품이다.
ex) 추상클래스: 붕어빵 기계 부품(붕어빵틀 하나) -> (일반)클래스 : 붕어빵기계(손잡이가 있고 위아래 뚜껑이 있는 붕어빵틀) -> 객체 생성
5. 추상 클래스의 객체 생성(자체로는 객체 생성 불가)
- 방법1 : 추상 클래스를 일반 클래스로 상속하여 객체 생성
abstract class Human{
abstract void show();
}
class Student extends Human{
@override // 상속해서 자식 안에서 완정
void show(){ .... }
}
Human hs = new Student();
Student std = new Student();
- 방법2 : 익명이너클래스 사용
abstract class Human{
abstract void show();
}
// Human hstd = new Human() ; 불가능, 왜냐면 show()라는 미완성 메서드를 가지고 있으므로
Human hstd = new Human(){ // 중괄호 안에 안되는 이유를 되게 완성시켜 준다.
void show(){ ... } //미완성 메서드를 이 메서드로 완성하여 객체를 생성
};
* 익명이너클래스를 사용하면 컴파일러가 내부적으로 클래스를 생성한 후 메서드 오버라이딩 수행
(클래스의 이름은 알 수 없음)
- 방법1과 방법2의 장단점
. 방법 1 : 추상클래스를 일반클래스로 상속하여 객체 생성 => 객체를 여러 개 생성할 수 있음
객체는 클래스 이름만 알고 있으면 몇 개건 만들 수 있다.
단 복잡해 보이기는 함 클래스를 만들어야 하기 때문
객체를 여러개 만들고자 할때 좋음
abstract class Human{
abstract void show();
}
class Student extends Human{
@override // 상속해서 자식 안에서 완정
void show(){
.....
}
}
public static void main(String[] args){
Student hong = new Student();
hong.show();
Student park = new Student();
park.show();
}
- 방법2 : 익명이너클래스 사용
클래스를 모르기 때문에 객체를 만들때마다 구현부분을 다 작성해야 함
딱 한번만 쓸것이라면 익명이 좋음(이벤트 처리 등)
객체를 한번만 쓸 것이면 유리
abstract class Human{
abstract void show();
}
Human hstd01 = new Human(){
@Override
void show(){ ... }
};
Human hstd02 = new Human(){
@Override
void show(){ ... }
};
================================
package abstractexam;
//미완성 메소드(=추상메소드)를 가진 클래스는 추상클래스
// abstract
public abstract class Animal {
//완성메소드
public void cry() {
System.out.println("동물의 울음 소리");
}
//완성메소드 - {}이 있으면 완성, 없으면 추상메소드
public void show() { }
//추상 메소드 - 미완성 메소드, body부분을 구현하지 않은것, {}이 없음
// 완성 메소드 앞에 abstract 를 붙이면 추상 메소드
public abstract void sound();
public abstract void run();
public abstract void drive();
}
------------
package abstractexam;
//Cat 클래스 - 추상 클래스
//부모인 Animal의 sound 추상메소드 구현하지 않았으므로
public abstract class Cat extends Animal {
@Override
public void run() {
System.out.println("고양이가 달린다");
}
@Override
public void drive() {
System.out.println("자동차가 주행중이다.");
}
}//end of Cat class
//class Dog extends Animal{
//
//}//end of Ddog class
------------------
package abstractexam;
public class Dog extends Animal{
@Override
public void sound() {
System.out.println("멍멍");
}
@Override
public void run() {
System.out.println("강아지가 달린다.");
}
@Override
public void drive() {
System.out.println("강아지가 자동차를 타고 있다.");
}
}
------------
package abstractexam;
public class AnimalExam {
public static void main(String[] args) {
Dog dog = new Dog();
dog.cry();
dog.sound();
dog.run();
dog.drive();
System.out.println();
System.out.println("------------------------");
//Cat cat = new Cat();//추상클래스라 객체 생성이 안된다.
}
}