2011-03-04 14 views
10

Considere esto sintácticamente correcta pseudocódigo (?):¿Es este un uso apropiado del polimorfismo?

class Event { 
public: 
    virtual int getID() const = 0; 
    virtual int getSize() = 0; 
    virtual void* getData() = 0; 
    virtual void setData() = 0; 
    //(I cannot define data at this level 'cos I don't know what it is yet) 
} 

class SpecialEvent : class Event { 
public: 
    virtual int getPGNID() const = 0; 
    int getSourceAddress() {return source_address;} 
    int setSourceAddress(int source_address) {this->source_address = source_address;} 
protected: 
    int source_address; 
} 

template <typename T, typename E> 
class EventWrapper : public E { 
    T data; 
public: 
    static int EVENT_ID; 
    //implements everything in Event...EVENT_ID is assigned at runtime by some registry 
} 

class AnEvent : public EventWrapper<int, Event> { 
    //public methods specific to AnEvent... 
} 

class AnotherEvent : public EventWrapper<long, SpecialEvent> { 
    int getPGNID() const {static int ID = 10; return ID;} 
} 

class TheProcessingClass { 
    AnEvent event1; 
    AnotherEvent event2; 

    void process(Event& e); 
    void process(SpecialEvent& e); 

    void doSomething() { 
     process(event1); //should invoke process(Event&) 
     process(event2); //should invoke process(SpecialEvent&) 
    } 
} 

Esencialmente, tengo una clase contenedora que envuelve los datos de tipo T y hereda de algún tipo de E (en este caso Event o SpecialEvent) ...

que inicialmente iba a crear dos clases contenedoras EventWrapper y SpecialEventWrapper hasta que me di cuenta de que ambas clases tendrían exactamente el mismo código en el mismo (siempre que se extiende desde algún tipo de Event)

En primer lugar, esto suena como un diseño basado en políticas. Sin embargo, el Events no tiene ningún comportamiento especial ... solo contienen algunos datos ... ¿Estoy abusando de este patrón?

En segundo lugar, ¿hay una mejor manera de hacerlo? Estoy simplificando mucho las cosas aquí, pero será apreciado ningún indicio ...

EDITAR He actualizado mi ejemplo ... en definitiva, las clases de procesamiento están escuchando para Eventos y deben tomar medidas basadas en el Evento . Espero que esto ayude ...

+0

+1 para "pseudocódigo sintácticamente correcto" =) – fouronnes

Respuesta

1

Sugiero agregar el proceso() como una función miembro del evento de la clase.

class Event { 
    int getID() const; 
    void process(); 
    //class stuff 
} 

class SpecialEvent : class Event { 
    int getSpecialID() const; 
    void process(); //special version of process() 
    //class stuff 
} 


class TheProcessingClass { 
    Event event1; 
    SpecialEvent event2; 

    void doSomething() { 
     event1.process(); 
     event2.process(); 
    } 
} 
+0

Yo ... pero 'Evento' realmente es más o menos un POD ... –

+0

@T Reddy: ¿Y qué? Si no necesita que sea un POD, hágalo funcionar como miembro. – Puppy

0

He jugado con su código por un tiempo. Me parece que está tratando de hacer algo muy parecido a boost::any

Si no, mi principal consejo es utilizar una interfaz abstracta real para Event y SpecialEvent. El diseño que tienes es solo polimorfismo parcial debido a que SpecialEvent tiene un método, y aún más importante, un método de IDENTIDAD, que no anula el evento :: getId. Eso "se siente" muy mal y creo que está garantizado para llevarlo a las dificultades más adelante cuando llegue a depender del concepto de Id de cualquier manera genérica.

En su diseño debe establecer una distinción clara entre identidad de clase (tipo) e identidad de objeto (instancia). Hasta ahora, parece que solo está trabajando con identidad de objeto (instancia); de lo contrario, su (s) método (s) id (es) sería (n) estático (s). RTTI se puede usar para establecer la identidad de clase pero dependiendo de los tipos reales derivados es un antipatrón clásico y generalmente indica polimorfismo roto. Nunca he tenido necesidad de RTTI, ni siquiera para fines de registro.

0

El código de tecla para responder a su pregunta son las dos funciones de proceso y lo que hacen. ¿Es incorrecto pasar un evento especial o un contenedor de eventos derivado de SpecialEvent a la función process(Event&)? Si es así, entonces este no es un uso apropiado del polimorfismo.

+0

No creo que sea incorrecto pasar un evento especial a algo que solo maneja eventos ... lo que sea que esté escuchando es posible que a Events no le importe que sea de tipo SpecialEvent ... –

Cuestiones relacionadas