abstract
추상메서드
- 자식 클래스에서 반드시 오버라이딩해야만 사용할 수 있는 메소드
- 자식 클래스에서 재정의해서 사용하는 메서드는 부모클래스에서의 구현이 의미가 없으므로 추상 메서드로 선언
*동적 바인딩으로 인해 부모클래스로 참조해도 오버라이드된 자식의 메서드로 사용
추상클래스
- 추상 메서드를 선언해 놓고 상속을 통해 자식 클래스에서 메서드를 완성하도록 유도하는 클래스
- 객체화가 불가능하며 추상메서드를 가질 수 있는 클래스(추상 메서드가 없어도 추상클래스를 만들 수 있다.)
- 구현의 강제를 통해 프로그램의 안정성 향상(자식 클래스에서 추상 부모 클래스의 추상메서드를 오버라이드 하지 않으면 컴파일 에러가 난다.)
문법
- 추상메서드가 있는 클래스는 추상클래스로 선언 되어야 한다.
public abstract class Vehicle {
private int curX, curY;
public void reportPosition() {
System.out.printf("차종: %s: 현재 위치: (%d, %d)%n", this.getClass().getSimpleName(), curX, curY);
}
public abstract void addFuel();
}
- 내부에 abstract 메서드가 있다면 자식 클래스에서는 오버라이딩을 해야한다.
abstract class Vehicle {
private int curX, curY;
public void reportPosition() {
System.out.printf("차종: %s: 현재 위치: (%d, %d)%n", this.getClass().getSimpleName(), curX, curY);
}
public abstract void addFuel();
}
public class ElectricCar extends Vehicle{
@Override
public void addFuel() {
System.out.printf("차종: %s: 연료 주입: %s%n", this.getClass().getSimpleName(), "충전");
}
}
- 자식클래스에서 오버라이딩을 하지 않으면 자식클래스에 abstract 메서드가 남아있으므로 자식클래스 또한 abstract클래스가 되어야 한다.
abstract class Vehicle {
private int curX, curY;
public void reportPosition() {
System.out.printf("차종: %s: 현재 위치: (%d, %d)%n", this.getClass().getSimpleName(), curX, curY);
}
public abstract void addFuel();
}
public abstract class ElectricCar extends Vehicle{
}
- 구현부가 없는 메서드가 있으므로 객체생성은 불가능하다.
abstract class Vehicle {
private int curX, curY;
public void reportPosition() {
System.out.printf("차종: %s: 현재 위치: (%d, %d)%n", this.getClass().getSimpleName(), curX, curY);
}
public abstract void addFuel();
}
public class VehicleTest{
public static void main(String[] args) {
Vehicle vehicle=new Vehicle();
}
}
Cannot instantiate the type Vehicle
- 상위 클래스 타입으로 자식을 참조하는 것이 가능하다.
abstract class Vehicle {
private int curX, curY;
public void reportPosition() {
System.out.printf("차종: %s: 현재 위치: (%d, %d)%n", this.getClass().getSimpleName(), curX, curY);
}
public abstract void addFuel();
}
class ElectricCar extends Vehicle{
@Override
public void addFuel() {
System.out.printf("차종: %s: 연료 주입: %s%n", this.getClass().getSimpleName(), "충전");
}
}
public class VehicleTest{
public static void main(String[] args) {
Vehicle vehicle=new ElectricCar();
vehicle.addFuel();
}
}
차종: ElectricCar: 연료 주입: 충전
- 추상메서드를 하나도 가지고 있지 않아도 된다.(외부에서 객체생성을 막기 위함)
public abstract class Vehicle {
private int curX, curY;
public void reportPosition() {
System.out.printf("차종: %s: 현재 위치: (%d, %d)%n", this.getClass().getSimpleName(), curX, curY);
}
}
코드
추상 클래스,추상 메서드 전
class Vehicle {
private int curX, curY;
public void reportPosition() {
System.out.printf("차종: %s: 현재 위치: (%d, %d)%n", this.getClass().getSimpleName(), curX, curY);
}
public void addFuel() {
System.out.println("연료가 필요합니다!");
}
}
class DieselSUV extends Vehicle{
private int curX, curY;
public void reportPosition() {
System.out.printf("차종: %s: 현재 위치: (%d, %d)%n", this.getClass().getSimpleName(), curX, curY);
}
public void addFuel() {
System.out.printf("차종: %s: 연료 주입: %s%n", this.getClass().getSimpleName(), "경유");
}
}
class ElectricCar extends Vehicle{
private int curX, curY;
public void reportPosition() {
System.out.printf("차종: %s: 현재 위치: (%d, %d)%n", this.getClass().getSimpleName(), curX, curY);
}
public void addFuel() {
System.out.printf("차종: %s: 연료 주입: %s%n", this.getClass().getSimpleName(), "충전");
}
}
public class VehicleTest{
public static void main(String[] args) {
Vehicle[] vehicles= {new DieselSUV(),new ElectricCar()};
for (Vehicle v:vehicles) {
v.addFuel();
}
}
}
- Vehicle의 addFuel()(1)메서드는 ElectricCar(2),DieselSUV(3)에서 모두 오버라이딩 하고 있어 구현된 내용이 쓰이고 있지 않다.
- 모든 자식 클래스에서 재정의 하고 있기 때문에 부모 클래서의 메서드 구현이 무의미하다.
- 구현부를 없애는 간단한 표현과 자식클래스에서 반드시 구현해야하는 강제성이 필요하다.
추상 클래스,추상 메서드 적용
abstract class Vehicle {
private int curX, curY;
public void reportPosition() {
System.out.printf("차종: %s: 현재 위치: (%d, %d)%n", this.getClass().getSimpleName(), curX, curY);
}
public abstract void addFuel();
}
class ElectricCar extends Vehicle{
@Override
public void addFuel() {
System.out.printf("차종: %s: 연료 주입: %s%n", this.getClass().getSimpleName(), "충전");
}
}
class DieselSUV extends Vehicle{
@Override
public void addFuel() {
System.out.printf("차종: %s: 연료 주입: %s%n", this.getClass().getSimpleName(), "경유");
}
}
public class VehicleTest{
public static void main(String[] args) {
Vehicle[] vehicles= {new DieselSUV(),new ElectricCar(),new Vehicle()};
for(Vehicle v:vehicles) {
v.addFuel();
}
}
}
생성자관련
- 추상클래스는 new를 통해 객체를 생성하는 것은 불가능하기에 객체를 생성할때 초기화를 해주는 생성자가 없는줄 알았지만 존재가 가능하다.추상클래스를 상속받은 자식클래스에서 super를 통해 생성자 호출 및 참조가 가능하다.
abstract class Vehicle {
private int curX, curY;
Vehicle(int x,int y){
this.curX=x;
this.curY=y;
}
public void reportPosition() {
System.out.printf("현재 위치: (%d, %d)%n", this.curX, this.curY);
}
public abstract void addFuel();
}
class ElectricCar extends Vehicle{
ElectricCar(int x,int y){
super(x,y);
}
@Override
public void addFuel() {
System.out.printf("차종: %s: 연료 주입: %s%n", this.getClass().getSimpleName(), "충전");
}
}
public class VehicleTest{
public static void main(String[] args) {
Vehicle vehicle1=new ElectricCar(10,10);
vehicle1.reportPosition();
}
}
현재 위치: (10, 10)
유익한 글이었습니다.