JAVA

[ Java ] - 추상클래스 / 템플릿 메서드

algml0703 2022. 9. 5. 23:13
반응형

추상클래스 (abstract class)

추상클래스는 상위클래스에서 하위클래스에 구현되어야할 메서드들을 생성하여 주고, 그 구체적인 내용은 하위클래스에서 정의되도록 하는 것이다. 추상클래스를 상속받은 클래스는 상위클래스에서 abstract로 지정된 메서드들을 재정의해주거나, 또는 하위클래스 자신도 abstract로 선언해주어야 한다.

* 추상클래스는 new 키원드를 사용하여 인스턴스를 객체를 생성할 수 없다.

* 추상클래스는 하나 이상의 추상 메서드를 갖는다.

* 추상클래스는 class 앞에 abstract라고 선언하여 준다. 

public abstract class Shape {
    private String type;

    public Shape(String type) {
        this.type = type;
    }

    // 추상메서드
    public abstract void draw();
}
public class AbstractAssist {
    public static void main(String[] args) {
        Shape shape = new Shape();
        // Shape is abstract; cannot be instanticated
    }
}
public abstract class Computer {
	// abstract 메서드를 갖기 위해서는 해당 클래스도 abstract로 선언해주어야 한다.
	// 추상 클래스는 인스턴스화 될 수 없다.
	public abstract void display ();
	// body값 즉 {}를 통해 그 내용을 구현해주지 않는 경우에는 abstract로 선언해주어야 한다.
	public abstract void typing ();
	
	public void turnoff() {
		System.out.println("==turn off===");
	}
}

 

ex)

Computer 클래스

package abstractpackage;

public abstract class Computer {
	public abstract void display ();
	public abstract void typing ();
    
	public void turnon() {
		System.out.println("==turn on===");
	}
	
	public void turnoff() {
		System.out.println("==turn off===");
	}
}

 

Desktop 클래스

package abstractpackage;

public class Desktop extends Computer {

	@Override
	public void display() {
		System.out.println("Desktop display()");
	}

	@Override
	public void typing() {
		System.out.println("Desktop typing()");
		
	}
}

Notebook 클래스

package abstractpackage;

public abstract class Notebook extends Computer {

	@Override
	public void display() {
		System.out.println("Notebook display()");
	}
}

MyNotebook 클래스 

package abstractpackage;

public class MyNotebook extends Notebook {

	@Override
	public void typing() {
		System.out.println("mynotebook display()");
	}

}

main 실행 클래스

package abstractpackage;

public class ComputerTest {
	public static void main (String[] args){
		// Computer c1 = new Computer ();
        	// Computer는 추상클래스여서 인스턴스로 생성할 수 없다.
		Computer c2 = new Desktop();
		// Computer c3 = new Notebook();
		
		Computer c4 = new MyNotebook();
		
		c4.display();
		c2.display();
	}

}

템플릿 메서드

일종의 시나리오/틀 을 갖추고, final 메서드로 선언되어 하위클래스에서 해당 메서드를 재정의할 수 없는 것을 의미한다.

아래의 코드를 예시로 하여 풀어서 이야기하면, Car가 run 되는 순차적인 시나리오는 시동을 켜고, 운전을 하고, 창을 닦고, 멈추고, 세차를 하고, 차의 시동을 끄는 것이다. 이때 어떠한 방식으로 운전을 하고 차를 멈추고, 세차를 하는 등의 구체적 기능은 하위클래스에서 선언해주는 것이다.

** abstract 메서드로 구현하는 것과 일반적인 메서드로 구현하되 {}를 기능을 구체화하지 않고 생성하는 것의 차이는, abstract로 선언한 메서드는 하위클래스에서 반드시 오버라이딩 되어야 하는 부분이고, 일반 메서드로 되어있는 것은 재정의되지 않아도 상관없다는 것이다.

ex1)

Car 클래스

package template;

public abstract class Car {
	public abstract void drive();
	public abstract void stop();
	public abstract void wiper();
	
	public void washCar() {
		
	};
	
	public void startCar() {
		System.out.println("시동을 켭니다.");
	}
	public void turnOff() {
		System.out.println("시동을 끕니다.");
	}
	// 템플릿 메서드 
	// final로 선언되어 하위클래스에서 재정의되지 않는다.
	public final void run() {
	// final public void run() { 
	// final은 앞에다 써도 큰 상관없다.	
	
		startCar();
		drive();
		wiper();
		stop();
		washCar();
		turnOff();
	}
}

ManualCar 클래스

package template;

public class ManualCar extends Car {

	@Override
	public void drive() {
		System.out.println("운전을 합니다.");
		System.out.println("사람이 핸들을 조작합니다.");
	}
	
	@Override
	public void wiper() {
		System.out.println("비나 눈의 양에 따라 자동으로 조절됩니다.");
	}

	@Override
	public void stop() {
		System.out.println("시동을 끕니다.");
	}
	
// 상위클래스에서 final로 선언한 메서드는 하위클래스에서 재정의할 수 없다.
//	public void run() {
//		
//	}

}

AICar 클래스

package template;

public class AICar extends Car {

	@Override
	public void drive() {
		System.out.println("자율주행합니다.");
		System.out.println("자동차가 스스로 방향을 전환합니다.");
	}
	
	@Override
	public void wiper() {
		System.out.println("비나 눈의 양에 따라 자동으로 조절됩니다.");
	}

	@Override
	public void stop() {
		System.out.println("자동차가 스스로 멈춥니다.");
	}
	
	@Override
	public void washCar() {
		System.out.println("자동으로 세차가 완료됩니다.");
	}

}

main 실행되는 클래스

package template;

public class CarTest {

	public static void main(String[] args) {
		Car myCar = new ManualCar();
		myCar.run();
		
		System.out.println("======");
		
		Car yourCar = new AICar();
		yourCar.run();
		
	}
}

위의 코드 실행시 아래와 같은 결과값이 나오게 된다. 상위클래스에서 abstract로 선언된 메서드는 하위클래스에서 반드시 선언되어 재정의 되어야 하지만, 일반적인 메서드로 생성된 것은 하위클래스에서 재정의를 해줄 수도 있고, 해주지 않을 수 도 있다.

ex2)

PlayerLevel 클래스

package gamelevel;

public abstract class PlayerLevel{
    public abstract void run();
    public abstract void jump();
    public abstract void turn();
    public abstract void showLevelMessage();
    
    final public void go(int count) {
    	run();
        for(int i = 0; i<count; i++) {
        	jump();
        }
        turn();
    }
}

Player 클래스

package gamelevel;

public class Player {
    private PlayerLevel level;
    
    public Player() {
    	level = new BeginnerLevel();
        level.showLevelMessage();
    }
    
    public PlayerLevel getLevel() {
    	return level;
    }
    
    public void upgradeLevel(PlayerLevel level) {
    	this.level = level;
        level.showLevelMessage();
    }
    
    public void play(int count){
    	level.go(count);
    }

}

BeginnerLevel 클래스

package gamelevel;

public class BeginnerLevel extends PlayerLevel {
	@Override
	public void run() {
		System.out.println("천천히 달립니다.");
	}

	@Override
	public void jump() {
		System.out.println("달릴 수 없습니다.");
	}

	@Override
	public void turn() {
		System.out.println("돌 수 없습니다.");
	}

	@Override
	public void showLevelMessage() {
		System.out.println("====초보자 레벨입니다.");
	}
}

AdvancedLevel 클래스

package gamelevel;

public class AdvancedLevel {
	@Override
	public void run() {
		System.out.println("빨리 달립니다.");		
	}

	@Override
	public void jump() {
		System.out.println("높이 점프 합니다.");		
	}

	@Override
	public void turn() {
		System.out.println("돌 수 없습니다.");		
	}

	@Override
	public void showLevelMessage() {
		System.out.println("===중급 레벨입니다.");		
	}
}

SuperLevel 클래스

package gamelevel;

public class SuperLevel {
	@Override
	public void run() {
		System.out.println("빨리 달립니다.");		
	}

	@Override
	public void jump() {
		System.out.println("높이 점프 합니다.");		
	}

	@Override
	public void turn() {
		System.out.println("돌 수 없습니다.");		
	}

	@Override
	public void showLevelMessage() {
		System.out.println("===중급 레벨입니다.");		
	}
}

MainBoard 클래스

package gamelevel;

public class MainBoard{
	public static void main(String[] args){
    		Player player = new Player();
        	player.play(1);
        
        	AdvancedLevel aLevel = new AdvancedLevel();
        	player.upgradeLevel(aLevel);
        	player.play(2);
        
        	SuperLevel sLevel = new SuperLevel();
        	player.upgradeLevel(sLevel);
        	player.play(3);
    }
}

 

 

 

 

출처

https://www.inflearn.com/course/%EC%9E%90%EB%B0%94-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%9E%85%EB%AC%B8#curriculum

 

반응형

'JAVA' 카테고리의 다른 글

[ Java ] -JSP 활용 기본  (0) 2022.09.14
[ Java ] - 인터페이스  (0) 2022.09.06
[ Java ] - Static과 final 키워드  (0) 2022.09.05
[ Java ] - 상속과 다형성  (0) 2022.09.04
[ Java ] - 이클립스에서 디버깅 하는 법  (0) 2022.09.04