Frage Ist dies eine angemessene Verwendung von Polymorphismus?


Betrachten Sie diesen syntaktisch korrekten (?) Pseudocode:

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&)
    }
}

Im Wesentlichen habe ich eine Wrapperklasse, die Daten vom Typ T umschließt und von einem bestimmten Typ erbt E (in diesem Fall Event oder SpecialEvent) ...

Ich wollte ursprünglich zwei Wrapper-Klassen erstellen EventWrapper und SpecialEventWrapper bis ich herausfand, dass beide Klassen genau den gleichen Code haben würden (so lange er sich von einer Art von Code erstreckte) Event)

Zunächst einmal klingt das nach einem richtlinienbasierten Design. Aber die Events hab kein besonderes Verhalten ... sie halten nur ein paar Daten ... missbrauche ich dieses Muster?

Zweitens, gibt es einen besseren Weg, dies zu tun? Ich vereinfache die Dinge hier sehr, aber alle Einsichten werden geschätzt ...

BEARBEITEN Ich habe mein Beispiel aktualisiert ... Kurz gesagt, die Verarbeitungsklassen warten auf Ereignisse und sollten auf der Grundlage des Ereignisses Maßnahmen ergreifen. Ich hoffe das hilft...


10
2018-03-04 19:05


Ursprung


Antworten:


Ich schlage vor, process () als Memberfunktion des Klassenereignisses hinzuzufügen.

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();
    }
}

1
2018-03-04 20:02



Ich habe eine Weile mit deinem Code gespielt. Es scheint mir, dass Sie versuchen, etwas sehr Ähnliches zu tun boost :: any

Wenn nicht mein wichtigster Rat ist, eine echte abstrakte Schnittstelle für Ereignis und SpecialEvent zu verwenden. Das Design, das Sie haben, ist nur teilweise Polymorphie aufgrund der Tatsache, dass SpecialEvent eine Methode hat, und noch wichtiger eine IDENTITY-Methode, die das Event :: getId nicht überschreibt. Das fühlt sich sehr schlecht an und ich glaube, dass es dich garantiert später in Schwierigkeiten bringen wird, wenn du dich auf das generische Konzept verlassen kannst.

In Ihrem Entwurf müssen Sie eine klare Unterscheidung zwischen Klassen- (Typ-) Identität und Objekt- (Instanz-) Identität treffen. Bis jetzt scheinen Sie nur mit der Identität des Objekts (der Instanz) zu arbeiten, ansonsten wäre Ihre Methode id () statisch. RTTI kann verwendet werden, um die Klassenidentität zu etablieren, aber abhängig von tatsächlich abgeleiteten Typen ist es ein klassisches Anti-Muster und zeigt normalerweise einen gebrochenen Polymorphismus an. Ich habe RTTI noch nie gebraucht, nicht einmal für den Holzeinschlag.


0
2018-03-05 14:08



Der Schlüsselcode, um Ihre Frage zu beantworten, sind die zwei Prozessfunktionen und was sie tun. Ist es inkorrekt, ein SpecialEvent oder einen EventWrapper zu übergeben, der von SpecialEvent abgeleitet wurde? process(Event&) Funktion? Wenn dies der Fall ist, dann ist dies keine angemessene Verwendung von Polymorphismus.


0
2018-03-06 01:16