Notice
Recent Posts
Recent Comments
관리 메뉴

Developer Gonie

[2주차] 49. 추상클래스, 반드시 만들어야할 것에 대해 미완성된 밑그림을 그려두는 것 본문

K-DigitalTraining 강의/1. Java

[2주차] 49. 추상클래스, 반드시 만들어야할 것에 대해 미완성된 밑그림을 그려두는 것

이대곤 2022. 5. 27. 10:26

* 추상클래스란?

추상클래스는 하위 클래스가 반드시 만들어야할 것에 대해 미완성된 밑그림을 그려두는 것과 같은데, 이를 사용하는 목적중 하나는 다음과 같다. 개발 프로젝트에서 설계자와 코더는 일반적으로 다른사람인데, 설계자의 입장에서 추상 클래스로 설계 규격을 만들어 두는 것이 좋다. 코더에게 추상 클래스를 상속해서 구체적인 클래스를 만들도록 지시하면 되기 때문이다. 주요 사용 목적은 이름대로 추상화를 위해 쓰인다.

 

추상메소드를 가질 수 있다는점, 추상화를 위해 쓰인다는점, 미완성 상태라서 이것만으로는 객체를 생성할 수 없다는 점, 추상클래스 타입의 참조변수는 자식클래스 객체들의 주소를 담을 수 있다는 점(다형성)에서 인터페이스와 매우 유사한데, 둘에는 구분되는 큰 차이도 있으니 이 둘의 차이를 잘 알아두었다가 상황에 맞는 것을 골라 쓸 수 있어야 한다. 아래의 상황은 추상클래스를 쓰기 더 좋은 상황이다. 다른말로 인터페이스로는 불가능한 것들이기도 하다.

 

"만약, 아래의 문장 중 하나가 당신의 상황에 적용된다면 '추상클래스' 사용을 고려해라." (인터페이스는 불가능한 것들)

1) 완성된 메소드와 같은 코드라인을 공유할 필요가 있는 관련 클래스가 여럿 존재하는 경우

2) 상수가 아닌 상태를 수정할 수 있는 non-final   변수를 정의하길 원하는 경우

3) public 이상의 접근제어자(protected, private)이 필요한경우

 

추상클래스는 생성자, 멤버변수, 완성된 메소드, 미완성 메소드(추상 메소드) 를 가질 수 있으며, 추상 메소드는 0개 이상 가질 수 있다. (즉, 0개도 가능하다는 말) 일반 클래스와 구분되도록 class 이름 왼쪽편에 abstract를 붙여주고, 상속 키워드는 일반 클래스와 같게 'extends'를 사용한다. 즉, 일반 클래스와 같게 이름을 여러개 나열하여 여러개를 상속받는 것은 불가능하다.(다중상속 불가)

 

<추상클래스, 인터페이스 공통점>

1) 이것만으로는 객체를 생성할 수 없다. 추상화된 상태로 미완성 상태이기 때문에 그런것인데, 상속받은 클래스에서
    추상메소드를 완성시킨 다음에 이 자식 클래스를 통해 객체를 생성하거나, 익명클래스를 이용해서 추상메소드를
    완성시켜 객체를 생성하거나 하는 것만 가능함.

 

2) 추상클래스를 상속받는 경우 자식클래스는 상속받은 추상메서드를 무조건 완성시켜줘야 한다. 안그러면 에러발생
    위 경우, 자식 클래스에도 abstract를 붙여 컴파일 에러를 제거할 순 있지만 그러면 객체 생성이 불가해짐. 

    (자식 클래스에도 abstract를 붙여 에러를 제거하는게 가능한건 추상클래스 끼리 상속이 가능해서 그러함)

코드

abstract class Shape {

	Shape() {
		System.out.println("Shape 생성자");
	}

	void make() {
		System.out.println("도형 그리기");
	}
    
	// 미완성 메서드(=추상메서드),
	abstract void draw();
	abstract void delete();
}// 추상클래스 Shape

class Circle extends Shape {
	Circle() {
		// super(); 자동으로 추가됨
		System.out.println("Circle 생성자");
	}

	// make() 메서드도 상속받지만 미완성 draw(), delete() 까지 상속받음
	// 물려받은 미완성 메서드는 자식에서 무조건 완성해줘야 한다.
	void draw() {
		System.out.println("원을 그린다.");
	}

	void delete() {
		System.out.println("원을 지운다.");
	}

}// Circle

class Rectangle extends Shape {
	Rectangle() {
		// super(); 자동으로 추가됨
		System.out.println("Rectangle 생성자");
	}

	void draw() {
		System.out.println("사각형을 그린다.");
	}

	void delete() {
		System.out.println("사각형을 지운다.");
	}
}// Rectangle

public class Ex06_10_추상클래스 {
	public static void main(String[] args) {
		// Shape s = new Shape(); -> 추상클래스로는 객체를 만들 수 없음.

		Circle c = new Circle();
		Rectangle r = new Rectangle();
        
		System.out.println();
		c.make();   // 상속받은 멤버함수 
		c.draw();   // 상속받은 미완성 메서드를 구현한 멤버함수
		c.delete(); // 상속받은 미완성 메서드를 구현한 멤버함수
		System.out.println();
        
		r.make();
		r.draw();
		r.delete();
		System.out.println();

		Shape[] arr = new Shape[2];
		arr[0] = c; // (Shape)c 업캐스팅이 자동으로 이뤄짐
		arr[1] = r; // (Shape)r 업캐스팅이 자동으로 이뤄짐
        
		for (int i = 0; i < arr.length; i++) {
			arr[i].draw();   // 부모클래스(추상클래스)의 메소드를 상속받아 오버라이드한거라 부모 타입으로 자식 메소드를 접근 가능 
			arr[i].delete(); // 부모클래스(추상클래스)의 메소드를 상속받아 오버라이드한거라 부모 타입으로 자식 메소드를 접근 가능 
		}
	}
}

실행결과

Shape 생성자
Circle 생성자
Shape 생성자
Rectangle 생성자

도형 그리기
원을 그린다.
원을 지운다.

도형 그리기
사각형을 그린다.
사각형을 지운다.

원을 그린다.
원을 지운다.
사각형을 그린다.
사각형을 지운다.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Comments