JAVA

[Java] abstract

sagesse2021 2021. 11. 1. 09:03
반응형

static을 쓰는 경우 클래스명(참조변수)로 메서드를 호출할 수 있다

/*
* 추상메서드(Abstract Method)
* - 메서드 바디(= 구현부, {})가 존재하지 않는 메서드 = 미완성 메서드
*   => 실행 코드가 없으므로 실행(호출)될 수 없는 메서드
* - 메서드 선언부 접근제한자 뒤에 abstract 키워드를 붙여서 선언
*   => 바디가 없으므로 메서드 마지막을 세미콜론(;)으로 마무리
* - 메서드 실행 코드(바디)가 없으므로 외부에서 호출되면 안되는 메서드
*
* < 추상메서드 정의 기본 문법 >
* [접근제한자] abstract 리턴타입 메서드명([매개변수...]);
* -------------------------------------------------------------
* 추상클래스(Abstract Class)
* - 인스턴스를 생성할 수 없는 미완성 클래스
*   => 내부에 추상메서드를 가지고 있을 경우
*      추상메서드가 호출되면 안되므로 인스턴스 생성을 못하게 차단함
* - class 키워드 앞에 abstract 키워드를 붙여서 정의
* - 추상메서드 뿐만 아니라 일반메서드, 멤버변수, 생성자를 가질 수 있음
*   => 추상메서드가 없는 메서드도 추상클래스로 정의할 수 있음
* - 인스턴스는 생성할 수 없지만, 상속을 통한 슈퍼클래스로 사용하거나
*   다형성 활용을 위한 참조변수 타입으로 사용 가능함
*   => 추상메서드를 포함하는 추상클래스를 상속받는 서브클래스에서는
*      반드시 오버라이딩을 통해 추상메서드 바디{} 를 구현해야한다!
*      즉, 추상메서드 오버라이딩을 강제할 수 있다!
*      (what 에 대한 강제, how 는 서브클래스에게 위임)
* - 추상메서드에 대한 구현을 강제함으로써 코드의 강제성 및 통일성 향상
*
* < 추상클래스 정의 기본 문법 >
* [접근제한자] abstract class 클래스명 {
* 		// 멤버변수
* 		// 생성자
* 		// 일반메서드
* 		// 추상메서드
* }
*
*/
public class Ex {

	public static void main(String[] args) {
	
		// 추상클래스인 AbstractClass 인스턴스 생성
//		AbstractClass ac = new AbstractClass();// 컴파일 에러 발생!, 추상클래스는 인스턴스 생성불가
		
		// 추상클래스를 상속받은 서브클래스 인스턴스 생성
		SubClass sc = new SubClass();
		sc.normalMethod();
		sc.abstractMethod();
		sc.subClassMethod();
		
		// 추상클래스를 참조변수 타입으로 활용 가능 = 업캐스팅을 통한 다형성
		AbstractClass ac = new SubClass(); //업캐스팅
		ac.normalMethod();  // 공통(상속된) 메서드
		ac.abstractMethod(); // 공통(상속된) 메서드
//		ac.subClassMethod(); //참조영역의 축소로 보이지 않는 메서드 
		
		System.out.println("==========================");
		
		// Flyer 클래스를 상속받은 SuperMan, Bird, AirPlane 인스턴스 생성
		SuperMan sm = new SuperMan();
		sm.takeOff();
		sm.fly();
		sm.land();
		
		Bird b = new Bird();
		b.takeOff();
		b.fly();
		b.land();
		
		AirPlane ap = new AirPlane();
		ap.takeOff();
		ap.fly();
		ap.land();
		
		System.out.println("-----------------------------");
		
		// SuperMan, Bird, Airplane -> Flyer 타입 업캐스팅하여 다형성 활용
		Flyer fl = new SuperMan();
		fl.takeOff();
		fl.fly();
		fl.land();
		
		fl = new Bird();
		fl.takeOff();
		fl.fly();
		fl.land();
		
		fl = new AirPlane();
		fl.takeOff();
		fl.fly();
		fl.land();
		
		
	}

}

abstract class AbstractClass {
	
//	public abstract void abstractMethod() {} //오류발생
	// => 추상메서드 정의 시 반드시 중괄호를 제거해야함(Abstract methods do not specify a body)

	public abstract void abstractMethod();
	// 추상메서드를 갖는 클래스는 반드시 추상클래스로 선언되어야 한다!
	// => class 키워드 앞에 abstract 키워드 필수!
	
	//추상클래스가 추가로 가질 수 있는 것
	public void normalMethod() {} //일반 메서드
	public AbstractClass() {} //생성자
	String member; //인스턴스 변수
}

//추상클래스 AbstractClass 를 상속받는 서브클래스 SubClass 정의	
class SubClass extends AbstractClass {
	 //추상클래스를 상속받은 서브클래스는 반드시 추상메서드 오버라이딩 필수!
	// => 바디를 갖지 않는 추상메서드의 바디를 구현(implement)하는 작업
	@Override
	public void abstractMethod() {
		System.out.println("서브클래스에서 오버라이딩(구현)된 추상메서드!");
	}
	
	public void subClassMethod() {
		System.out.println("서브클래스에서 정의한 메서드!");
	}
	
}
/*
 * 슈퍼맨, 새, 비행기의 공통점 : 비행 가능
 * => 공통점을 추출하여 상위클래스로 정의하되,
 *    각 서브클래스에서 비행 기능을 반드시 구현하도록 강제성을 부여
 */
abstract class Flyer {
	// 모든 날아다니는 것들에 대한 이륙, 비행, 착륙 메서드 정의
	// => 슈퍼클래스로 사용할 Flyer 클래스의 메서드들에는
	//    실행할 코드가 불필요하므로 추상메서드로 정의하고
	//    추상메서드를 포함하는 Flyer 클래스를 추상클래스로 정의
	public abstract void takeOff();
	
	public abstract void fly();
	
	public abstract void land();
}

//Flyer 클래스를 상속받는 SuperMan, Bird, AirPlane 클래스 정의
class SuperMan extends Flyer {

	@Override
	public void takeOff() {
		System.out.println("SuperMan 이륙!");		
	}

	@Override
	public void fly() {
		System.out.println("SuperMan 비행!");
	}

	@Override
	public void land() {
		System.out.println("SuperMan 착륙!");
		
	}
}

class Bird extends Flyer {

	@Override
	public void takeOff() {
		System.out.println("Bird 이륙!");
		
	}

	@Override
	public void fly() {
		System.out.println("Bird 비행!");
		
	}

	@Override
	public void land() {
		System.out.println("Bird 착륙!");
		
	}
	
}

class AirPlane extends Flyer {

	@Override
	public void takeOff() {
		System.out.println("AirPlane 이륙!");
		
	}

	@Override
	public void fly() {
		System.out.println("AirPlane 비행!");
		
	}

	@Override
	public void land() {
		System.out.println("AirPlane 착륙!");
		
	}
	
}
/*
서브클래스에서 오버라이딩(구현)된 추상메서드!
서브클래스에서 정의한 메서드!
서브클래스에서 오버라이딩(구현)된 추상메서드!
==========================
SuperMan 이륙!
SuperMan 비행!
SuperMan 착륙!
Bird 이륙!
Bird 비행!
Bird 착륙!
AirPlane 이륙!
AirPlane 비행!
AirPlane 착륙!
-----------------------------
SuperMan 이륙!
SuperMan 비행!
SuperMan 착륙!
Bird 이륙!
Bird 비행!
Bird 착륙!
AirPlane 이륙!
AirPlane 비행!
AirPlane 착륙!
*/
public class Ex2 {

	public static void main(String[] args) {
		
	}

}
abstract class AbstractClass2 {
	
	public abstract void method1();
	public abstract void method2();
}

//추상메서드 2개를 갖는 추상클래스를 상속받아 서브클래스 정의
abstract class MiddleClass extends AbstractClass2 {
	//상속받은 추상메서드 2개 중 하나만 구현하는 경우
	// => 추상메서드가 구현되지 않은 채 그대로 존재할 경우 
	//    해당 서브클래스도 추상클래스로 선언해야한다!
	@Override
	public void method1() {
		System.out.println("MiddleClass에서 구현한 method1()");
	}
}

//추상메서드를 모두 구현하지 않은 서브클래스(추상클래스) MiddleClass 를
//상속받는 서브클래스 SubClass2 정의
class SubClass2 extends MiddleClass {
	// method1() 메서드는 MiddleClass 에서 이미 구현되어 있으므로 강제성 X
	// 여전히 강제성이 남아있는 method2() 메서드는 반드시 구현해야한다!
	@Override
	public void method2() {
		System.out.println("SubClass2 에서 구현한 method2()");
	}
	
	
}
public class Test2 {

	public static void main(String[] args) {

//		Vehicle v = new vehicle(); // 인스턴스 생성 불가
		
		// 추상클래스 Vehicle 타입을 참조변수로 활용
		Vehicle v = new ElectricCar();
		v.reportPosition();
		v.addFuel();
		
		v = new DiselCar();
		v.reportPosition();
		v.addFuel();
	}

}

abstract class Vehicle {
	int curX, curY; // 현재 위치 좌표를 저장하는 변수
	
	public void reportPosition() { //서브클래스에서 오버라이딩 옵션
		System.out.println("현재위치: " + curX + ", " + curY );
	}
	
//	public void addFuel() {
////		System.out.println("자동차의 연료 공급!");
//	}
	// => 차량마다 연료 공급 방법이 달라지므로 오버라이딩을 해야하며
	//    오버라이딩 강제성을 부여하기 위해 추상메서드로 정의할 수 있다!
	public abstract void addFuel();//서브클래스에서 구현 필수
}

//Vehicle 클래스를 상속받는 ElectricCar, DieselCar 클래스 정의
//=> ElectricCar 의 addFuel() : "전기차 충전소에서 배터리 충전!" 
//=> DieselCar 의 addFuel() : "주유소에서 디젤 연료 공급!"
class ElectricCar extends Vehicle {

	@Override
	public void addFuel() {	
		System.out.println("전기차 충전소에서 배터리 충전!");
	}
	
}

class DiselCar extends Vehicle {

	@Override
	public void addFuel() {
		System.out.println("주유소에서 디젤 연료 공급!");
	}
	
}
/*
현재위치: 0, 0
전기차 충전소에서 배터리 충전!
현재위치: 0, 0
주유소에서 디젤 연료 공급!
*/

 

반응형

'JAVA' 카테고리의 다른 글

[Java] 상수(Constant), 열거형(enum type)  (0) 2021.11.01
[Java] 다형성 연습  (0) 2021.11.01
[Java] 다형성(Polymorphism)  (0) 2021.11.01
[Java] 상속(inheritance) - 동적 바인딩  (0) 2021.10.31
[Java] instanceof  (0) 2021.10.31