El anterior post me ha hecho reflexionar, y más aún, cuando varias personas me han cuestionado la validez de lo que yo creía correcto. Por ello voy a hacer un esfuerzo de sintetizar los argumentos a favor y en contra de las opciones planteadas y por el camino seguro que aprendo algo.
Planteamiento del problema
La cuestión era la siguiente (si quieres luego aportar comentarios, lee cuidadosamente esto):
Para permitir que una clase corra como un trhead, ¿heredo de un thread o bien implemento un interfaz runnable?
Pero, ¡detente!, antes de ponerte a responder vamos, pausadamente, a plantear un posible escenario.
Supongamos que desarrollas una serie de clases en tu programa, por ejemplo, un clásico mata marcianos como el space invaders.

Imaginemos que desarrollamos una jerarquía de clases como esta:
+ Marciano (Clase base abstracta para todos los marcianos)
|
—— MarcianoRaso (Marciano simplón sin inteligencia, solo se mueve y dispara aleatoriamente)
|
—–+ MarcianoExperimentado (Es algo más inteligente, más resistente y más rápido)
|
|——– GranJefeMarciano ( Este es mucho más resistente, más rápido y es capáz de hacer movimientos especiales)
Todos comparten el hecho de SER un marciano, cada hijo en la jerarquía aporta algo más y además su representación gráfica es distinta.
Una vez programada esta jerarquía nos damos cuenta de que necesitamos mover los marcianos por la pantalla de forma independiente (podríamos hacerlo de otra forma, pero el caso es llegar a la cuestión que nos trae, que es la discusión sobre los threads). Para ello usaremos la clase Thread, y tenemos varias formas.
a) Podemos hacer que Marciano herede de thread de forma que todos los marcianos automáticamente sean un thread
b) Podemos hacer que las clases “hoja” además de heredar de su clase padre, implementen el interfaz “runnable”
Ventajas e inconvenientes de ambos métodos
caso A
En este caso, un respetado compañero (Gorka), me comenta que (Gorka, si esta cita no es correcta en este caso puntualizamelo y lo corrijo):
El coste de solucionarlo heredando será mucho menor que implementando una interfaz, porque heredarás gran parte de eso que llaman los gurús “boilerplate code” ya hecho. Además, siempre se puede solucionar el problema de la herencia múltiple utilizando la agregación, de la forma “Es un Hilo que mueve un Marciano
Esto nos deja una jerarquía como la siguiente:
+ Thread
|—+ Marciano (Clase base abstracta para todos los marcianos)
|
|—— MarcianoRaso (Marciano simplón sin inteligencia, solo se mueve y dispara aleatoriamente)
|
|—–+ MarcianoExperimentado (Es algo más inteligente, más resistente y más rápido)
|
|———— GranJefeMarciano ( Este es mucho más resistente, más rápido y es capáz de hacer movimientos especiales)
En este caso, sobreescribimos el método “run” y todos los marcianos son un thread con sus posibilidades.
Ventajas
De una tacada tenemos que todos los marcianos son un thread y poniendo en el run su comportamiento automaticamente tienen “vida propia”
Inconvenientes
Hay dos cosas que no me gustan de esta opción:
a) Asumes en tu diseño inicial que cada marciano ha de ser controlado por un thread y te has comprometido a ello desde la clase base. Si luego decides que podrias hacer un solo thread que vaya moviendo cada marciano secuencialmente tu diseño no es flexible.
b) Conceptualmente has asumido que un marciano es un “thread” y eso, repito, conceptualmente, no es cierto.
caso B
Haces que los marcianos instanciables puedan ser ejecutados por un thread implementando el interfaz runnable.
A primera vista puede parecer muy similar pero tiene ciertas implicaciones, veamos como queda la jerarquía de clases:
+ Marciano (Clase base abstracta para todos los marcianos)
|
—— MarcianoRaso implements Runnable
|
—–+ MarcianoExperimentado implements Runnable
|
|——– GranJefeMarciano implements Runnable
Esto hace que las clases que implementen el interfaz escriban un método “run” (el trabajo que lleva con respecto a heredar y sobreescribir el “run” es exactamente el mismo).
Recordemos que cada marciano tiene un comportamiento diferente y cada uno querrá escribir su propio run.
Ventajas
a) Si más adelante quieres que por ejemplo la clase Marciano herede de otra clase superior que aporta funcionalidad, por ejemplo “SerDelEspacioExterior” puedes hacerlo, no así en el caso de la herencia donde tendrías que buscar otra solución. Por lo tanto mantenemos la flexiblidad en el diseño.
b) Se mantiene la coherencia conceptual, un Marciano, no es un Thread, es un ser del espacio exterior.
c) No comprometes desde la clase base a que tus marcianos sean controlados por un thread, es más, puedes elegir cuales quieres que sean controlados por un thread y cuales no. Si usas la herencia al tener que ponerlo desde la clase base no puedes elegir esto.
Inconvenientes
Pues no se me ocurre ningúno, salvo el hecho de tener que crear un Thread y luego pasarle el marciano para que lo ejecute.
Conclusiones
A la espera de nuevas aportaciones sigo inclinándome por la opción del interfaz. No obstante me comprometo a añadir a otro nuevo post cada aportación que me enviéis, siempre que no faltéis al respeto, claro está.
Es decir, no me valen aportaciones del tipo “no tienes ni puta idea”, o, “eso no se hace así”, necesito argumentos o refutaciones de mis argumentos.