¿Cómo abstraer la interfaz a dos clases similares?
Estoy escribiendo un motor de Ultimate Tic-Tac-Toe como un ejercicio de programación (para mí, no para tareas) y tengo dos clases similares. Una es una clase MiniBoard
que contiene un solo tablero normal de Tic-Tac-Toe, y otra Board
que es en sí mismo un gran tablero de Tic-Tac-Toe compuesto por 9 MiniBoards
, uno para cada celda grande del juego.
También tengo una función int getState( ... )
que devuelve un número determinado según si un tablero está ganado, perdido, empatado o en progreso. Dado que hay una obvia simetría entre MiniBoard
y Board
, me parece que debería poder hacer que mi función getState
acepte tanto MiniBoard
como Board
como argumento, ya que ambos deben estar ganados, empatados, perdidos o en progreso.
Al principio pensé en hacer que Board
heredara de MiniBoard
, pero este enfoque resultó innecesariamente complicado porque la funcionalidad de MiniBoard
es fundamentalmente diferente de Board
, aunque representan objetos muy similares. Tampoco sigue realmente la relación “ES UN” de la herencia de POO.
La idea que tengo actualmente, pero no sé si es buena, es hacer una clase base abstracta BaseBoard
que defina las propiedades y métodos comunes como virtuales y luego hacer que Board
y MiniBoard
deriven de BaseBoard
. Luego definiría mi función para obtener el estado como:
int getState(const BaseBoard &board)
El principal problema que tengo con este enfoque es que no sé de antemano qué tipo de propiedades y métodos necesitaré para mi BaseBoard a futuro. Y si alguna vez llego al punto de tener una cadena larga de herencia que comienza con BaseBoard y quiero cambiar algo, eso significaría que tendría que cambiar cada definición de clase en la cadena de herencia. ¿Cuál es la solución a este problema? ¿Simplemente derivar más clases?
En general, ¿es este un buen enfoque para resolver el problema? ¿Cuáles son los pros y los contras? No estoy muy familiarizado con las clases base abstractas en C++. Cualquier ayuda es apreciada.
davy.ai
Solución
Utilizar una clase base abstracta
BaseBoard
parece ser un buen enfoque para resolver el problema. Al definir las propiedades y métodos comunes como virtuales enBaseBoard
, podemos hacer queBoard
yMiniBoard
deriven deBaseBoard
e implementen su propia funcionalidad específica. Esto nos permite pasar objetosBoard
yMiniBoard
a la funcióngetState
que solo requiere una referencia deBaseBoard
.El problema de no conocer las propiedades y métodos de antemano para
BaseBoard
se puede resolver diseñandoBaseBoard
para que incluya solo la funcionalidad básica compartida entreBoard
yMiniBoard
. Cualquier funcionalidad adicional que sea específica deBoard
oMiniBoard
se puede implementar en esas clases respectivas.En cuanto a ventajas y desventajas, algunas ventajas potenciales de utilizar una clase base abstracta incluyen una mejor organización del código y la reducción de la duplicación de código, así como la capacidad de tratar objetos de manera genérica. Algunas desventajas potenciales incluyen la complejidad adicional de gestionar las relaciones de herencia y una posible disminución en el rendimiento debido al uso de funciones virtuales.
En general, utilizar una clase base abstracta para resolver este problema parece ser una solución razonable, pero sería importante considerar cuidadosamente el diseño de
BaseBoard
para asegurarse de que incluya solo la funcionalidad básica compartida entreBoard
yMiniBoard
.