Method chaining + inheritance don't play well together?

后端 未结 15 798
北荒
北荒 2020-12-08 22:20

Consider:

// member data omitted for brevity

// assume that \"setAngle\" needs to be implemented separately
// in Label and Image, and that Button does need         


        
15条回答
  •  悲&欢浪女
    2020-12-08 22:54

    Is a Button really a Label? You seem to be violating the Liskov substitution principle. Perhaps you should consider the Decorator pattern to add behaviors to Widgets.

    If you insist on the structure as is, you can solve your problem like so:

    struct Widget {
        Widget& move(Point newPos) { pos = newPos; return *this; }
        virtual ~Widget();  // defined out-of-line to guarantee vtable
    };
    
    struct Label : Widget {
        Label& setText(string const& newText) { text = newText; return *this; }
        virtual Label& setAngle(double newAngle) { angle = newAngle; return *this; }
    };
    
    struct Button : Label {
        virtual Label& setAngle(double newAngle) {
            backgroundImage.setAngle(newAngle);
            Label::setAngle(newAngle);
            return *this;
        }
    };
    
    int main() {
        Button btn;
    
        // Make calls in order from most-specific to least-specific classes
        btn.setText("Hey").move(Point(0,0));
    
        // If you want polymorphic behavior, use virtual functions.
        // Anything that is allowed to be overridden in subclasses should
        // be virtual.
        btn.setText("Boo").setAngle(.5); 
    }
    

提交回复
热议问题