추상 메서드(Abstract Method)
- 메서드 바디(=구현부, {})가 존재하지 않는 메서드 = 미완성 메서드
-> 실행코드가 없으므로 실행(호출)될 수 없는 메서드
- 메서드 선언부 접근제한자 뒤에 abstract 키워드를 붙여서 선언
-> 바디가 없으므로 메서드 마지막을 세미콜론(;)으로 마무리
- 메서드 실행코드(바디)가 없으므로 외부에서 호출되면 안 되는 메서드
< 추상 메서드 정의 기본 문법 >
[접근제한자] abstract 리턴 타입 메서드명([매개변수...]);
추상 클래스(Abstract Class)
- 인스턴스를 생성할 수 없는 미완성 클래스
-> 내부에 추상 메서드를 가지고 있을 경우 추상 메서드가 호출되면 안되므로 인스턴스 생성을 못 하게 차단함
- class 키워드 앞에 abstract 키워드 붙여서 정의
- 추상 메서드 뿐만 아니라 일반 메서드, 멤버변수, 생성자를 가질 수 있음
-> 추상 메서드가 없는 클래스도 추상 클래스로 정의할 수 있음
- 인스턴스를 생성할 수 없지만, 상속을 통한 슈퍼클래스로 사용하거나 다형성 활용을 위한 참조변수 타입으로 사용 가능함
-> 추상 메서드를 포함하는 추상클 래스를 상속받는 서브 클래스에서는 반드시 오버라이딩을 통해 추상 메서드 바디{}를 구현해야 한다! 즉, 추상 메서드 오버라이딩을 강제할 수 있다! (What 에 대한 강제, HOW 는 서브 클래스에게 위임)
- 추상 메서드에 대한 구현을 강제함으로써 코드의 강제성 및 통일성 향상
< 추상 클래스 정의 기본 문법 >
[접근제한자] abstract class 클래스명 {
// 멤버변수
// 생성자
// 일반 메서드
// 추상 메서드
}
abstract class AbstractClass {
// public abstract void abstractMethod() {} // 오류 발생!
// -> 추상 메서드 정의 시 반드시 중괄호를 제거해야 함!
// -> Abstract methods do not specify a body
public abstract void abstractMethod();
// -> 추상 메서드를 갖는 클래스는 반드시 추상 클래스로 선언되어야 한다!
// -> The abstract method abstractMethod in type AbstractClass
// can only be defined by an abstract class
// -> class 키워드 앞에 abstract 키워드 필수!
// 추상클래스가 추가로 가질 수 있는 것
public void normalMethod() {} // 일반 메서드
public AbstractClass() {} // 생성자
String member; // 인스턴스 변수
}
//추상클래스 AbstractCLass 를 상속 받는 서브클래스 SubClass 정의
class SubClass extends AbstractClass {
// 추상클래스를 상속받는 서브클래스는 반드시 추상메서드 오버라이딩 필수!
// The type SubClass must implement
// the inherited abstract method AbstractClass.abstractMethod()
// => 바디를 갖지 않는 추상메서드의 바디를 구현(implement) 하는 작업
// Ctrl Shift S + V
@Override
public void abstractMethod() {
System.out.println("서브클래스에서 오바라딩(구현)된 추상메서드!");
}
public void subClassMethod() {
System.out.println("서브클래스에서 정의한 메서드!");
}
}
// 추상 클래스를 상속받은 서브 클래스 인스턴스 생성
SubClass sc = new SubClass();
sc.normalMethod();
sc.abstractMethod();
sc.subClassMethod();
TEST
/*
* 슈퍼맨, 새, 비행기의 공통점: 비행 가능
* -> 공통점을 추출하여 상위클래스로 정의하되,
* 각 서브 클래스에서 비행 기능을 반드시 구현하도록 강제성을 부여
*
* Flyer 추상 클래스 정의
* -> 이륙(takeOff), 비행(fly), 착륙(land) 추상 메서드 정의
* -> 슈퍼맨, 새, 비행기 서브 클래스 생성
* 각 메서드 호출 시 "슈퍼맨(or 새 or 비행기) 이륙!",
* "슈퍼맨 비행", "슈퍼맨 착륙" 출력
*/
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("슈퍼맨 이륙!");
}
@Override
public void fly() {
System.out.println("슈퍼맨 비행!");
}
@Override
public void land() {
System.out.println("슈퍼맨 착륙!");
}
}
class Bird extends Flyer {
@Override
public void takeOff() {
System.out.println("새 이륙!");
}
@Override
public void fly() {
System.out.println("새 비행!");
}
@Override
public void land() {
System.out.println("새 착륙!");
}
}
class AirPlane extends Flyer {
@Override
public void takeOff() {
System.out.println("비행기 이륙!");
}
@Override
public void fly() {
System.out.println("비행기 비행!");
}
@Override
public void land() {
System.out.println("비행기 착륙!");
}
}
// Flyer 클래스를 상속받은 SuperMan, Bird, AirPlane 인스턴스 생성
SuperMan a = new SuperMan();
a.takeOff();
a.fly();
a.land();
Bird b = new Bird();
b.takeOff();
b.fly();
b.land();
AirPlane c = new AirPlane();
c.takeOff();
c.fly();
c.land();
// SuperMan, Bird, AirPlane -> Flyer 타입으로 업캐스팅하여 다형성 활용
Flyer f = new SuperMan();
f.takeOff();
f.fly();
f.land();
f = new Bird();
f.takeOff();
f.fly();
f.land();
f = new AirPlane();
f.takeOff();
f.fly();
f.land();
// 추상 메서드 2개를 갖는 추상 클래스 정의
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()!");
}
}
TEST
package abstract_;
public class Test_2 {
public static void main(String[] args) {
// Vehicle v = new Vehicle(); // 인스턴스 생성 불가!
// 추상클래스 Vehicle 타입을 참조 변수로 활용
Vehicle v = new ElectricCar();
v.addFuel();
v.reportPosition();
v = new DieselCar();
v.addFuel();
v.reportPosition();
}
}
/*
* Vehicle 클래스 정의
* 멤버변수: curX, curY(int) 현재 좌표를 저장하는 변수
* 메서드: public void(리턴 타입 X, 매개 변수 X)
* -> "현재 위치 : curX, curY"
* addFuel(리턴 타입 X, 매개 변수 X)
* -> 차량마다 연료 공급 방법이 달라지므로 오버라이딩을 해야 하며
* 오버라이딩 강제성을 부여함
*/
abstract class Vehicle {
int curX, curY;
public void reportPosition() {
System.out.println("현재 위치: " + curX + "," + curY);
}
public abstract void addFuel();
}
/*
* Vehicle 클래스를 상속받는 ElectricCar, DieselCar 클래스 정의
* -> ElectricCar의 addFuel(): "전기차 충전소에서 배터리 충전!"
* -> DieselCar의 addFuel(): "주유소에서 디젤 연료 공급!"
*
*
*/
class ElectricCar extends Vehicle {
@Override
public void addFuel() {
System.out.println("전기차 충전소에서 배터리 충전!");
}
}
class DieselCar extends Vehicle {
@Override
public void addFuel() {
System.out.println("주유소에서 디젤 연료 공급!");
}
}
'⛏️ > JAVA' 카테고리의 다른 글
[JAVA] 28. 오브젝트 (0) | 2023.10.11 |
---|---|
[JAVA] 27. 인터페이스 (0) | 2023.10.05 |
[JAVA] 25. 상수 (0) | 2023.10.05 |
[JAVA] 24. 다형성 (0) | 2023.09.26 |
[JAVA] 23. 동적 바인딩 (0) | 2023.09.26 |