方法链+继承不能一起玩? [英] Method chaining + inheritance don't play well together?
问题描述
请考虑:
//为简洁省略成员数据
//假设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屋!