[JAVA]추상클래스와 추상메서드(Abstract)

@욕심쟁이

·

2020. 9. 11. 17:46

반응형

추상(Abstract)이란?

- 실체간에 공통되는 특성을 추출한것.

1. 추상클래스

 - 공통적인 특성을 추출해서 선언한 클래스

 - 용도 : 실체 클래스의 공통적인 특성(필드, 메소드)을 뽑아냄

    1) 공통된 필드와 메소드 이름을 통일할 목적

    2) 서브클래스를 작성할 때 시간 절약

 - 인스턴스 생성이 불가능한 클래스
   → 인스턴스 생성이 가능할 경우 추상메서드 호출이 가능하므로 인스턴스 생성을 못하도록 막아놓은 클래스
 - 상속을 통해 서브클래스에서 추상메서드를 구현하도록 강제하는 용도의 클래스로 주로 사용      
 - 추상클래스가 가질수 있는 멤버
     생성자, 일반멤버변수, 상수, 일반메서드, "추상메서드"
 - 클래스 정의시 class키워드 앞에 "abstract"키워드를 붙임
 - 인스턴스 생성은 불가능하지만 참조변수 타입은 사용가능다형성 적용가능

 <추상클래스정의 기본문법>

abstarct class 클래스명 {
	//필드
    //생성자
    //메소드(일반메서드, 추상메서드)
}  

2. 추상메서드

 - 메서드 구현부(바디,{})가 없는 메서드(= 실행할 코드가 없는 메서드)
  **메서드란? 호출받으면 코드를 실행하는 것
 - 구현부가 없기 때문에 외부로부터 호출되어도 실행할코드가 없음
     따라서, 추상메서드를 포함하는 클래스는 반드시 추상클래스로 선언해야한다!

 - 추상클래스에 추상메서드가 없어도된다
 - 추상메서드 정의시 리턴타입 앞에 "abstract"키워드를 붙임

 <추상메서드 정의 기본 문법>

 [접근제한자]abstract 리턴타입 메서드 명([매개변수,....);

3. 추상메서드 재정의

- 코드의 통일성

- 메소드의 선언만 통일하고, 실행 내용은 다름

   (슈퍼클래스의 추상메서드바디는 없어야하고, 서브클래스의 추상메서드바디는 있고 내용은 달라도 상관없음)

- 추상클래스는 추상메소드를 선언 해도되고 안해도됨

- 추상메서드는 추상클래스에서만 선언가능

- 슈퍼클래스의 메서드를 하위클래스가 강제로 적용시키고싶을때 추상메서드 지정

  상속받은 클래스에 추상메소드가 있으면 그 메서드는 재정의(구현 : Implement) 해야됨

- 추상메서드를 재정의하지않으면 자식클래스는 추상클래스가 되어야함

  자식클래스에서 부모의 추상 메서드를 오버라이딩하지 않으면 자식도 추상클래스가됨 

 → 추상메서드를 오버라이딩 할때까지 추상클래스 상속

 

예제1

public class Ex {
	public static void main(String[] args) {
		
		SubClass sc = new SubClass();//SubClass의 인스턴스 생성

		sc.normalMethod();
		sc.abstractMethod1();
		sc.abstractMethod2();
		
		//추상클래스로 인스턴스 생성불가
		//AbstractClass ac = new AbstractClass();
		//MiddleClass mc = new MiddleClass();
		
		//업캐스팅은 가능
		AbstractClass ac  = sc;
		ac.normalMethod();
		ac.abstractMethod1();
		ac.abstractMethod2();
		MiddleClass mc = sc;
		mc.normalMethod();
		mc.abstractMethod1();
		mc.abstractMethod2();
		
	}

}
//추상클래스
abstract class AbstractClass{
	String var; // 일반멤버변수
	
	public AbstractClass() {}// 생성자
	public void normalMethod() {
		System.out.println("추상클래스의 메서드!");
	}
	
	//추상메서드 abstractMethod()정의
	//=> 현재클래스는 반드시 추상클래스로 선언해야함(추상메서드가 있기때문)
	public abstract void abstractMethod1();
	public abstract void abstractMethod2();
}
 //추상클래스 AbstractClass를 상속받는 MiddleClass 정의
//=>2개의 추상메서드중 하나의 메서드만 오버라이딩
abstract class MiddleClass extends AbstractClass{
	//모든 추상메서드를 오버라이딩 하지않고, 일부만 구현할 겨우
	//여전히 추상메서드를 포함하게 되므로 일반클래스로 정의 할 수 없다!
	//=> 추상메서드를 모두 오버라이딩 하거나, 현재클래스를 추상클래스로 선언
	@Override
	public void abstractMethod1() {
		System.out.println("MiddelCalss 에서 구현한 추상메서드 abstractMethod1");
		
	}
		
}

//MiddleClass를 상속받는 SubClass 정의
//=> MiddleClasee에서 구현되지 않은 abstractMethod2()메서드에 대한
//구현책임이 발생함 => 반드시 구현
class SubClass extends MiddleClass{

	@Override
	public void abstractMethod2() {
		System.out.println("SubVLass에서 구현한 추상메서드 abstractMethod2()");
	}
	
	
}

예제2

public class Ex {

	public static void main(String[] args) {
				
		//Shap s = new Shap(); //=> 인스턴스화 불가(new하지말라)
		// Cannot instantiate the type Shap
		//=> 인스턴스화 불가능한 타입이르모 인스턴스 생성시 오류발생!
		
		//참조변수의 데이터 타입으로 사용은 가능
		Shap s = new Circle();
		s.draw();
		s = new Rectangle();
		s.draw();
		
	}

}
abstract class Shap{
	//public abstract void draw(); //추상메서드는 body{}를 가질수 없다.
	public abstract void draw(); //추상메서드는 추상클래스에만 정의되어야만 한다. => 추상메서드는 호출되어선 안되기 때문에
}

//2. 추상클래스 Shap을 상속받는 서브 클래스 Circle정의
//=>추상메서드가 존재하는 경우 서브클래스에서 수상메서드를 구현(implement)해야한다!
//  구현()과 오버라이딩은 동일한 기능이지만
//  메서드 바디{}를 구현하는데 목적이 있기때문에 다른용어로 표현함
class Circle extends Shap{
	//draw()메서드를 상속받아 구현(implement)해야함 => Overriding(Implements) 필수!
	@Override
	public void draw() { //must implement (바디를)구현해야한다!
		System.out.println("추상클래스로부터 상속받은 추상메서드를 오버라이딩");
		System.out.println("원그리기!");		
	}   //구현하기싫으면 추상클래스가 되어야하고 결국 자식의자식의 자식까지 구현(implement)할때까지 간다//빼면 상속 못받음
	
}

class Rectangle extends Shap{
	//추상메서드 오버라이딩에대한 강제성으로 부여되므로 개발자가 실수로 빠뜨릴 위험이 없어짐!
	@Override
	public void draw() {
		System.out.println("추상클래스로부터 상속받은 추상메서드를 오버라이딩");
		System.out.println("사각형 그리기!");		
	}
}

/*
 //==================================================================
   강제성을 부여하지 않고 클래스를 정의하게 될 경우 발생하는 문제점
 //==================================================================
class Shap{
	public void draw() {
		System.out.println("도형그리기");
	}
}

class Circel extends Shap{
	/*Shap클래스를 상속받는 Circle클래스는 draw()메서드를 갖게 되지만
	 * draw()메서드를 오버라이딩 하지않고 다른메서드를 정의하여
	 * 원을 그려도 부모(Shap) 입장에서는 강제할 방법이 없다! 
	public void CircleDrew() {
		System.out.println("원그리기");
	}
	
}
class Rectangle extends Shap{
	/* Shap클래스를 상속받는 Rectangle클래스는 draw()메서드를 갖게 되지만
	 * 실수로 인해 draw()메서드를 오버라이딩 하지않더라도
	 * 부모(Shap) 입장에서는 강제할 방법이 없다!
     
}

*/
반응형