方法链+继承不能一起玩? [英] Method chaining + inheritance don't play well together?

查看:115
本文介绍了方法链+继承不能一起玩?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑:

  //为简洁省略成员数据

//假设setAngle 需要单独实现
//在Label和Image中,并且Button需要继承
// Label,而不是说包含一个(etc)

struct Widget {
Widget& move(Point newPos){pos = newPos; return * this; }
};

struct Label:Widget {
Label& setText(string const& newText){text = newText; return * this; }
Label& setAngle(double newAngle){angle = newAngle; return * this; }
};

struct Button:Label {
Button& setAngle(double newAngle){
backgroundImage.setAngle(newAngle);
Label :: setAngle(newAngle);
return * this;
}
};

int main(){
Button btn;

// oops:Widget :: setText不存在
btn.move(Point(0,0))。setText(Hey);

// oops:调用Label :: setAngle而不是Button :: setAngle
btn.setText(Boo)。setAngle(.5);
}

任何解决这些问题的技巧?



示例:使用模板魔法使Button :: move return Button&




$ b

编辑很明显,第二个问题可以通过setAngle virtual来解决。



但第一个问题仍然没有以合理的方式解决!



我想这是不可能在C ++中做正确。非常感谢你的努力。

解决方案

对于第二个问题,使setAngle virtual应该做的。
$ b

对于第一个,没有简单的解决方案。 Widget :: move返回一个Widget,它没有setText方法。你可以做一个纯虚拟的setText方法,但这将是一个非常丑的解决方案。你可以重载move()在按钮类,但这是一个痛苦的维护。最后,你可能做一些模板。也许这样:

  //定义移动帮助函数
template< typename T>
T& move(T& obj,Point& p){return obj.move(p); };

//然后你的代码中有问题的行将如下所示:
move(btn,Point(0,0))setText(Hey);

我会让你决定哪个解决方案是最干净的。但是有什么特别的原因,你需要能够链接这些方法?


Consider:

// member data omitted for brevity

// assume that "setAngle" needs to be implemented separately
// in Label and Image, and that Button does need to inherit
// Label, rather than, say, contain one (etc)

struct Widget {
    Widget& move(Point newPos) { pos = newPos; return *this; }
};

struct Label : Widget {
    Label& setText(string const& newText) { text = newText; return *this; }
    Label& setAngle(double newAngle) { angle = newAngle; return *this; }
};

struct Button : Label {
    Button& setAngle(double newAngle) {
        backgroundImage.setAngle(newAngle);
        Label::setAngle(newAngle);
        return *this;
    }
};

int main() {
    Button btn;

    // oops: Widget::setText doesn't exist
    btn.move(Point(0,0)).setText("Hey");

    // oops: calling Label::setAngle rather than Button::setAngle
    btn.setText("Boo").setAngle(.5); 
}

Any techniques to get around these problems?

Example: using template magic to make Button::move return Button& or something.

edit It has become clear that the second problem is solved by making setAngle virtual.

But the first problem remains unsolved in a reasonable fashion!

edit: Well, I guess it's impossible to do properly in C++. Thanks for the efforts anyhow.

解决方案

For the second problem, making setAngle virtual should do the trick.

For the first one, there are no easy solutions. Widget::move returns a Widget, which doesn't have a setText method. You could make a pure virtual setText method, but that'd be a pretty ugly solution. You could overload move() on the button class, but that'd be a pain to maintain. Finally, you could probably do something with templates. Perhaps something like this:

// Define a move helper function
template <typename T>
T& move(T& obj, Point& p){ return obj.move(p); };

// And the problematic line in your code would then look like this:
move(btn, Point(0,0)).setText("Hey");

I'll let you decide which solution is cleanest. But is there any particular reason why you need to be able to chain these methods?

这篇关于方法链+继承不能一起玩?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆