오목 미션을 진행하면서 abstract class
와 interface
의 차이에 대해서 생각해보았다.
나는 abstract class
인 OmokPlayer
를 상속하는 BlackStonePlayer
, WhiteStonePlayer
클래스를 생성했다. 여기서 내가 interface
를 구현(implement)하는 것이 아닌 abstract class
를 상속(inheritance)하도록 만든 이유는 무엇일까?
abstract class OmokPlayer{
abstract val color: Color
protected var state: PlayerState = PlayerState.Placing
fun placeStone(
currentBoard: Board,
checkBoard: (Board) -> Unit,
decidePoint: (latestStone: Stone?, currentColor: Color) -> Point
): Board {
//돌을 두는 로직을 가지는 함수
}
abstract fun toNextPlayer(): Player
//다음 플레이어를 반환하는 함수
abstract fun isPossibleToPlace(board: Board, placingPoint: Point): Boolean
//특정 위치에 돌을 둘 수 있는지 없는지에 대한 함수
}
class BlackStonePlayer: OmokPlayer() {
override val color: Color = Color.Black
override fun isPossibleToPlace(board: Board, placingPoint: Point): Boolean {
//33, 44, 놓으려고 하는 위치에 돌이 놓여있는지에 대한 함수
}
override fun toNextPlayer(): Player {
//돌을 잘 두었으면 WhiteStonePlayer를 반환한다
}
}
class WhiteStonePlayer : Player() {
override val color: Color = Color.White
override fun isPossibleToPlace(board: Board, placingPoint: Point): Boolean {
//놓으려고 하는 위치에 돌이 놓여있는지에 대한 함수
}
override fun toNextPlayer(): Player {
//돌을 잘 두었으면 BlackStonePlayer를 반환한다
}
}
BlackStonePlayer
와 WhiteStonePlayer
의 중복되는 프로퍼티와 메서드isPossibleToPlace
, toNextPlayer
에 대해서 다르게 반응내가 abstract class를 사용한 이유이다.
interface
를 사용해도 되지 않을까?물론 interface
를 사용해 다형성을 이용하는 설계를 할 수도 있었을 것이다.
하지만 interface
와 abstract class
의 가장 큰 차이는 논리적으로 관련이 있는 클래스들의 계층 구조를 형성하는 것이다. abstract class
를 사용하기 위해서는 is-a 관계를 나타내는 상속(inheritance)을 사용하기 때문이다.
결론적으로 abstract class
는 논리적 또는 의미적으로 관련이 있는 클래스들에서 다형성을 이용하고 싶을때 사용한다고 생각한다.
interface
를 사용했다면?구현(implements)은 상속(inheritance)과 다르게 서로 논리적으로 관련이 적은 클래스들끼리도 필요에 의해 형제 타입처럼 묶어 버릴 수 있다. 필요에 따라서 자유롭게 붙였다 땠다 할 수 있는 것이 장점이다.
만약 YellowStonePlayer
가 추가되었다고 하자. 그리고 BlackStonePlayer
와 YellowStonePlayer
는 돌을 놓을때 제한되는 위치에 대한 룰이 있다고 한다면 다음과 같이 필요에 따라서 ForbiddenPlacingRule
이라는 interface
를 두어 필요한 클래스에 붙였다 뗐다 하는 방식으로도 구현해 보는 방법도 있을것 같다.
내가 왜 abstract class
를 사용했을까에 대해서 생각해보면서 interface
와의 차이에 대해서 학습했다.
abstract class
는 구현부를 가지는 메소드, 초기화된 프로퍼티를 가질 수 있다.interface
는 구현부가 없는 메소드만 가질 수 있다.abstract class
와 interface
를 사용할 때 표면적으로 드러나는 차이점 이외의 것들에 대해서도 한번씩 생각해보면 좋을것 같다.