블랙잭 미션은 상속과 인터페이스를 익히기 위한 미션이다. 미션을 시작하기 전에 연료주입이라는 가벼운 구현을 요구했는데, 이때 추상클래스과 인터페이스를 사용하라는 요구사항이 있었다. 인터페이스는 전략패턴을 하면서 사용해봤기 때문에 익숙했지만, 추상클래스는 아예 처음 구현해보는거라 낯설었다. 그래서 추상클래스와 인터페이스를 정리해보기로 했다.
추상클래스(Abstract Class)
추상 클래스는 abstract 키워드가 붙어있는 클래스를 말한다. abstract 메서드가 있을 수도 있고, 없을 수도 있다. 추상클래스는 인스턴스화될 수 없지만, 서브클래스로 사용될 수 있다.
<나의 생각>
추상 클래스는 구체적인 클래스 설계도이다. 예를 들어 Car
라는 추상 클래스가 있으면 필드에 자동차 이름, 가격 정도는 필수값으로 지정할 수 있다. 꼭 필요한 메서드도 지정할 수 있다, 예를 들어 자동차의 이름을 갖고오는 메서드가 모든 자동차에 필요한 기능이라면 getCarName()
을 미리 구현할 수 있다. 마찬가지로 기능이 필요하지만 자동차마다 다르게 구현되어야 한다면 추상메서드로 남겨둘 수 있다.(단, 추상메서드는 상속받은 클래스에서 구현되어야한다.)
public abstract class Car {
// declare fields
String carName;
int carPrice;
// declare nonabstract methods
public String getCarName() {
return carName;
}
// abstract methods
abstract int calculateFuelEfficiency();
}
인터페이스(Interface)
인터페이스는 클래스와 비슷한 참조 타입이다. 인터페이스에는 상수, 메서드 시그니쳐, 디폴트 메서드, 스태틱 메서드이 들어올 수 있다. 메서드 바디(중괄호{}로 감싸지는 부분)는 디폴트메서드랑 스태틱 메서드에만 존재할 수 있다. 인터페이스는 인스턴스화 될 수 없고, 구현체로 만들어지거나 다른 인터페이스에 extends 될 수 밖에 없다.
<나의 생각>
인터페이스는 기능 설계도이다.어떤 기능을 할 수 있는지 메서드가 담겨있고 작동하는 자동차에서 공통적으로 해야할 일들을 설계할 수 있다. 비슷하게 작동하는 기계라고 한다면 승용차 트럭이 해당 인터페이스를 사용할 수 있도록 구현할 수 있다.
public interface OperateCar {
// constant declarations, if any
// method signatures
// An enum with values RIGHT, LEFT
int turn(Direction direction,
double radius,
double startSpeed,
double endSpeed);
......
// more method signatures
}
public abstract class Participant {
protected final String name;
protected final HoldingCard holdingCard;
public Participant(String name, List<Card> cards) {
this.name = name;
this.holdingCard = new HoldingCard(cards);
}
public void receiveCard(Card card) {
holdingCard.add(card);
}
public abstract boolean isFinished();
}
public class Player extends Participant {
public Player(String name, List<Card> cards) {
super(name, cards);
}
public boolean isFinished() {
return holdingCard.isBust();
}
}
public class Dealer extends Participant {
private static final int DEALER_MIN_TOTAL = 17;
private static final String DEALER = "딜러";
public Dealer(List<Card> cards) {
super(DEALER, cards);
}
public boolean isFinished() {
return holdingCard.computeTotalScore() >= DEALER_MIN_TOTAL;
}
}
블랙잭 게임에서 플레이어와 딜러는 비슷한 역할을 한다. 아래는 내가 생각하는 딜러와 플레이어가 가져야할 상태와 기능이다.
<상태>
1. 이름
2. 보유 중인 카드
<기능>
1. 카드를 한 장 받는다.
2. 점수 합계를 구한다.
3. 카드를 더 받을 수 있는지를 확인한다.
두 인스턴스 모두 상태를 가져야하는데, 공통적인 부분이 많아 이를 구현하기 위해서 인터페이스보다는 추상 클래스가 적절하다고 판단하여 추상 클래스로 구현했다. 그리고 카드를 더 받았는지 확인하는 로직이 딜러와 플레이어가 다르기 때문에 추상메서드를 이용해서 다르게 구현해줬다.
https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html#:~:text=An%20abstract%20class%20is%20a,but%20they%20can%20be%20subclassed.
https://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html
https://www.baeldung.com/java-interfaces