Pregunta

Estoy creando una biblioteca de clases con muchas opciones diferentes para posibles personalizaciones. Por ejemplo, usted puede diseñar su clase para que pueda llevar a cabo FeatureX (), o puede diseñar su clase para que pueda llevar a cabo FeatureY ().

En circunstancias normales, sólo tendría que crear una interfaz IFeatureX con un método virtual pura llamada FeatureX, y otro IFeatureY interfaz con un método virtual pura llamada FeatureY. Si una clase tiene tanto FeatureX y FeatureY, se puede heredar de ambos, no hay problema.

Mi problema es, ¿y si una función / método requiere un objeto que puede realizar tanto FeatureX () y FeatureY ()? ¿Cómo expreso un tipo, preferentemente en C ++, pero una respuesta en Java podría ayudar también, para asegurar que tanto FeatureX y FeatureY están disponibles?

puedo crear otra interfaz IFeatureXY que hereda de IFeatureX y IFeatureY? Está bien ... si sólo hay dos características que podía salirse con la suya. Pero si hay decir ... 10 características, el número de posibles interfaces de vuelve masivo.

¿Hay una manera simple de hacer esto? He intentado resolver el problema utilizando plantillas y delegación C ++, pero no demasiado lejos. Estoy esperando que hay una solución simple para esto, y probablemente es uno que simplemente se pasa por alto.

Agradezco cualquier ayuda y asesoramiento que ustedes tienen.

Gracias.

¿Fue útil?

Solución

Si usted no tiene miedo de usar plantillas, puede hacer su función de una plantilla y utilizar SFINAE para comprobar si las dos interfaces:

template <class T>
void my_function(const T& data, typename enable_if_c<
    is_convertible<T*, IFeatureX*>::value && 
    is_convertible<T*, IFeatureY*>::value>::type*=0) {
  ...
}

Esto creará un método para cada tipo que se extiende ambas interfaces de características (se cuenta que el truco SFINAE no es necesario para que funcione; una plantilla sin restricciones iba a funcionar, pero sólo dejar de compilar cuando se pasa de un tipo que no hace cumplir con los requisitos).

Otra posibilidad es la creación de una interfaz IFeatureXY extendiéndose ambos, y utilizar esto en los parámetros de la función; esto tiene el inconveniente de que los tipos que hacer implementan ambas interfaces, pero no esta interfaz de la junta no serían utilizables con este método.

Además, puede pasar dos argumentos a la función, una por cada interfaz, y requieren que son punteros a un mismo objeto; esto es frágil, pero se puede endurecer al hacer alguna clase de plantilla para mantener las dos punteros - por ejemplo. product_type<IFeatureX*, IFeatureY*>, que se inicializa mediante el solo objeto en cuestión y que obstaculicen los dos tipos.

En Java, que probablemente se podría hacer lo mismo con las variables de tipo acotadas (si permiten que múltiples límites, no estoy seguro de que ahora).

Otros consejos

Lo primero que debe hacer es preguntar si está tratando de hacer algo que no se puede expresar simplemente, y si es así, pregúntese si es realmente vale la pena hacer?

Dado que usted no puede encontrar un modelo más simple de lo que quieres, vas a tener que pensar en las dependencias entre las opciones. Si se puede usar la función de X, independientemente de Feature Y, a continuación, hacer que las interfaces independientes o clases virtuales puras (según sea apropiado para el idioma.)

Si no se pueden utilizar de forma independiente, crea una clase que incluye tanto; preguntarse por qué quiere FeatureX y FeatureY como interfaces separadas, porque eso patrón de uso sugiere que no son independientes después de todo.

A pesar de que existen formas de agregar características completamente diferentes, es posible que desee pensar en el alcance de estas características añadidas. ¿Van a estar relacionado con su biblioteca principal de la clase? (Se podría argumentar que si no lo son no deben ser parte de ella)

Si tienen suficiente en común con las características de warrants adición se puede buscar algo así como el patrón decorador ( http : //en.wikipedia.org/wiki/Decorator_pattern ). Se le permite omitir algunas de las cuestiones torcidas con hacer cosas como esta.

Si desea ot hacerlo en c ++, ¿qué pasa con la herencia múltiple?

Es posible que usted está siendo demasiado grano fino. Considere una clase numérica - puede realizar la multiplicación, división, suma, resta, etc. Sin embargo, no sería crear interfaces separadas para cada una de estas operaciones - se crearía una interfaz llamada SupportsArithmetic (o lo que sea) que les cubría toda

WCF tiene muy buen patrón de cómo determinar si un objeto es compatible con alguna de las interfaces (o clase) utilizando IExtensionCollection<T>.Find<E>(). IExtensionCollection .

IFeatureX feature = argument.Find<IFeatureX>();

if (feature != null)
{
    // Find() returned an instance so there is an implementation
    // of IFeatureX available

   feature.FeatureX();
}

De esta manera se puede consultar su objeto por alguna de interfaz gráfica. Un método similar se utiliza en COM + en IUnknown :: QueryInterface ( ) .

¿Por qué usted necesita interfaces? Use plantillas:

template< typename T >
void some_function( const T& t )
{
    // use featureX functions
    t.fetatureX();

    // use featureY functions
    t.featureY();
}

Uso:

SomeClass x; // object with only X feature
some_function( x ); // compile time error, because featureY() doesn't exists
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top