En general, la covarianza le permite expresar más información en la interfaz de clase derivada que la verdadera en la interfaz de clase base. El comportamiento de una clase derivada es más específico que el de una clase base, y la covarianza expresa (un aspecto de) la diferencia.
Es útil cuando tiene jerarquías relacionadas de gubbins, en situaciones donde algunos clientes querrán usar una interfaz de clase base, pero otros clientes usarán la interfaz de clase derivada.Con const-corrección omitido:
class URI { /* stuff */ };
class HttpAddress : public URI {
bool hasQueryParam(string);
string &getQueryParam(string);
};
class Resource {
virtual URI &getIdentifier();
};
class WebPage : public Resource {
virtual HttpAddress &getIdentifier();
};
clientes, que saben que tienen una página web (navegadores, tal vez) sabe que es significativo a la vista Parámetros de consulta. Los clientes que usan la clase base Recurso no conocen tal cosa. Siempre vincularán el HttpAddress&
devuelto a una variable URI&
o temporal.
Si sospechan, pero no saben, que su objeto Resource tiene una HttpAddress, entonces pueden dynamic_cast
. Pero la covarianza es superior a "solo saber" y hacer el reparto por la misma razón por la que el tipado estático es útil en absoluto.
Hay alternativas - pegue la función getQueryParam
en URI
pero haga que hasQueryParam
devuelva falso para todo (satura la interfaz URI). Deje WebPage::getIdentifier
definido para devolver URL&
, devolviendo realmente un HttpIdentifier&
, y las personas que llaman realizan un inútil dynamic_cast
(desordena el código de llamada y la documentación de WebPage donde dice "se garantiza que la URL devuelta se puede convertir dinámicamente en HttpAddress"). Agregue una función getHttpIdentifier
a WebPage
(satura la interfaz WebPage
). O simplemente use la covarianza para lo que se supone que debe hacer, que es expresar el hecho de que un WebPage
no tiene un FtpAddress
o un MailtoAddress
, tiene un HttpAddress
.
Por último, existe un argumento razonable de que no debería haber jerarquías de gubbins, y menos relacionadas con las jerarquías de gubbins. Pero esas clases podrían fácilmente ser interfaces con métodos virtuales puros, así que no creo que afecte la validez de usar la covarianza.
Cuando leí la pregunta, mi reacción fue exactamente la misma. ¿Cuál es el problema? ¡No use tipos de retorno covariantes! –