Results 1 to 9 of 9

Thread: How to avoid type comparision using polymorphism

  1. #1
    Join Date
    Apr 2011
    Posts
    9
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default How to avoid type comparision using polymorphism

    Hi everybody!


    I'm facing a new problem while developing an application and I'd like to hear some advices regarding its design.

    I have a class (ObjectAction) which defines what should be done on specific situations. As I want to have different kinds of those "actions", I was thinking to define ObjectAction like this:

    Qt Code:
    1. class ObjectAction {
    2. public:
    3. virtual void perform(...) = 0;
    4. virtual void writeToFile() = 0:
    5. virtual void readFromFile(...) = 0;
    6. };
    To copy to clipboard, switch view to plain text mode 

    So I can define its behavior by subclassing ObjectAction. For example:

    Qt Code:
    1. class ExampleAction : public ObjectAction {
    2. public:
    3. QString getData() const { return data; }
    4. void setData(const QString& newData) { data = newData; }
    5. void perform(...) {
    6. qDebug() << data;
    7. }
    8. // Other definitions missing
    9. .......
    10. private:
    11. QString data;
    12. };
    13.  
    14. class OtherAction : public ObjectAction {
    15. public:
    16. ......
    17. void perform() { /*something else */ }
    18. .....
    19. private:
    20. QHash<QString, int> data;
    21. };
    To copy to clipboard, switch view to plain text mode 
    It seems to be the good choice, but there is a problem: I want to provide an editor which allows user to set the ObjectAction to use, and he should be able to change the action kind and its data, so in my editor, if the action is of type ExampleAction, I will show a QLineEdit with the current data, but if the action is of type OtherAction, I should show some other widget to allow modifying the QHash. The same thing applies when I need to construct the action from data read from a file. The question is: How should I determine the type? Or better, how should I draw the editor for each type?

    Thank you very much!
    Last edited by dancas2; 28th April 2012 at 18:09.

  2. #2
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: How to avoid type comparision using polymorphism

    if the action is of type ExampleAction, I will show a QLineEdit with the current data, but if the action is of type OtherAction, I should show some other widget to allow modifying the QHash
    You can add pure virtual method to ObjectAction class, and return different editor for each class:
    Qt Code:
    1. class ObjectAction {
    2. public:
    3. virtual void perform(...) = 0;
    4. virtual void writeToFile() = 0:
    5. virtual void readFromFile(...) = 0;
    6. virtual QWidget * createEditor() = 0;
    7. };
    8.  
    9. ...
    10.  
    11. class ExampleAction : public ObjectAction {
    12.  
    13. public:
    14.  
    15. QString getData() const { return data; }
    16. void setData(const QString& newData) { data = newData; }
    17. void perform(...) {
    18. qDebug() << data;
    19. }
    20. QWidget * createEditor(){
    21. return new StringEditor(...);
    22. }
    23.  
    24. // Other definitions missing
    25. .......
    26.  
    27. private:
    28. QString data;
    29.  
    30. };
    31.  
    32.  
    33.  
    34. class OtherAction : public ObjectAction {
    35. public:
    36. ......
    37. void perform() { /*something else */ }
    38. QWidget * createEditor(){
    39. return new HashEditor(...);
    40. }
    41. .....
    42. private:
    43. QHash<QString, int> data;
    44.  
    45. };
    To copy to clipboard, switch view to plain text mode 
    HashEditor and StringEditor can be both subclasses of QWidget, or a custom QWidget-based AbstractEditor type etc.

  3. #3
    Join Date
    Apr 2011
    Posts
    9
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: How to avoid type comparision using polymorphism

    Hi stampede, thanks for your reply!

    I had already considered that approach, but there are two reasons I don’t like it:

    1. It polutes the class declaration, because the editor is only needed in a separate application that allows user to manage the “actions” of some objects and then it’s saved to a file. In the main application I just need to read that file and “perform” them
    2. I would anyway need to figure the current action type in order to provide a QComboBox with action types and setting the current type there

    Thank you very much!

  4. #4
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: How to avoid type comparision using polymorphism

    I agree.
    You want to avoid type comparison, but you can't complete this without actually comparing something.
    So another way. You can see how, for example, QEvent and its subclasses are implemented - there is a type enumeration for each subclass in QEvent class, then its possible to distinguish between the subtypes, using this enumeration. So for your case:
    Qt Code:
    1. class ObjectAction {
    2. public:
    3. enum Type{
    4. Example,
    5. Other,
    6. ....
    7. }
    8. virtual Type type() const = 0;
    9. ...
    10. };
    11.  
    12. ...
    13.  
    14. class ExampleAction : public ObjectAction {
    15. public:
    16.  
    17. Type type() const{
    18. return Example;
    19. }
    20. ...
    21. private:
    22. QString data;
    23.  
    24. };
    25.  
    26. class OtherAction : public ObjectAction {
    27.  
    28. public:
    29.  
    30. Type type() const{
    31. return Other;
    32. }
    33. .....
    34. private:
    35. QHash<QString, int> data;
    36.  
    37. };
    To copy to clipboard, switch view to plain text mode 
    etc. (actually, its slightly different in QEvent, to allow user-defined events, but its not important right now)
    Then you can implement ActionEditors without modifying the Action impl.:
    Qt Code:
    1. #include "ObjectAction.h"
    2.  
    3. class ActionEditorCreator{
    4. QWidget * createEditor( ObjectAction * action ){
    5. switch(action->type()){
    6. case ObjectAction::Example :
    7. return new StringEditor(action);
    8. case ObjectAction::Other :
    9. return new HashEditor(action);
    10. }
    11. }
    12. };
    To copy to clipboard, switch view to plain text mode 
    Does it suits your needs better ? It solves 1) I guess.
    As for 2), what do you mean by " QComboBox with action types and setting the current type there", maybe I don't see the whole picture.

  5. The following user says thank you to stampede for this useful post:

    dancas2 (30th April 2012)

  6. #5
    Join Date
    Apr 2011
    Posts
    9
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: How to avoid type comparision using polymorphism

    Hi stampede, thanks again for your reply!

    Really I don't care if I have to compare a type (because I need it anyway), I just want to make it easy to add new action types later, without having to check those types in many places.

    Previously I had implemented something like your suggestion, but I was checking the type to decide what to perform, so I had to check the type not only in editor and action creation but in action "processor" too. Of course, by that way I had to store the data in a QVariant (or maybe a C++11 union, but that's not implemented in my compiler now), so I was wasting memory and I had to cast the data everytime I wanted to process the action.

    By this way there would be only two places where I have to check the type, so I think it is ok for me.

    As for 2), let me explain my situation a bit better. Some classes of my application have a QVector<ObjectAction*>, which defines what will do that class and the order they will do that. The editor just shows a list of the available actions and let you add some of them to some class (with the data needed for that action). But the user should be able to modify one action (including its type) if he wants, it wouldn't be good if he had to recreate the whole class or the whole actions just to change the type of one action!. So in my editor, there is a combo box with every action type, and the user choose the one he will use. Of course, if he changes the type, all the data of that action is lost, but there is no problem with it!.

    Anyway, there is a problem with your suggestion: resource handling. As the editor will be shown each time the user selects an "action", I would have to delete the old editor and create the new one. In my old design I had a QStackedWidget and just changed the page when the type changed (as the type is numeric). I would have to check the type to generate a new Action from UI, but I think I have no choice, right?

    Thank you very much!

  7. #6
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: How to avoid type comparision using polymorphism

    I would have to delete the old editor and create the new one
    Not necessary, you can create one editor for each action type, and just pass it different "action" instances to display and modify. Every object of given "Action" type will be modified the same way, only the data will change.
    For example, lets say you want to display different text in line edit placed on your widget. Probably you will only pass another QString instance into line edit, not delete old and create new line edit object.

  8. #7
    Join Date
    Apr 2011
    Posts
    9
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: How to avoid type comparision using polymorphism

    Not directly with the previous code, I think:

    Qt Code:
    1. class ActionEditorCreator{
    2. QWidget * createEditor( ObjectAction * action ){
    3. switch(action->type()){
    4. case ObjectAction::Example :
    5. return new StringEditor(action);
    6. case ObjectAction::Other :
    7. return new HashEditor(action);
    8. }
    9. }
    10. };
    To copy to clipboard, switch view to plain text mode 

    Anyway, don't worry. It's not that hard to solve.

    Thank you very much!

  9. #8
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: How to avoid type comparision using polymorphism

    Not directly with the previous code
    Sure, the code was just to present the previous idea

  10. #9
    Join Date
    Sep 2011
    Posts
    1,241
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to avoid type comparision using polymorphism

    This is where a factory would normally come in. You register the type/type-id with a function that creates the correct editor.

    so then the comparison is pushed deeper (e.g. into a map inside the factory), and you don't need to modify the factory for every new object (open/closed principle).
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

Similar Threads

  1. GraphicsLayer polymorphism concernings
    By tobyas in forum General Programming
    Replies: 3
    Last Post: 15th September 2010, 12:09
  2. Replies: 2
    Last Post: 22nd December 2009, 20:52
  3. Polymorphism interfaces in C++
    By ComaWhite in forum General Programming
    Replies: 2
    Last Post: 1st July 2009, 12:38
  4. polymorphism in java
    By mickey in forum General Programming
    Replies: 0
    Last Post: 13th November 2008, 16:34
  5. Polymorphism with static calls
    By niko in forum General Programming
    Replies: 12
    Last Post: 9th November 2007, 09:52

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.