所以我现在对D感兴趣了一段时间,而且我不久前搞砸了它。我已经开始重新审视它了,我真的喜欢它想要实现的目标,但我对我最喜欢的C ++设计选项有一个疑问......非虚拟接口。
我喜欢这个设计的是它允许在继承层次结构的“顶部”进行前后条件检查,日志记录和资源管理。这允许设计者指定一组相关类的所有常用功能,并将类的可自定义部分分解为非常小的功能。它还减少了需要在子类中编写的功能。另外,因为虚拟扩展点是私有的,所以它不会污染接口,或者允许用户直接调用特定于实现的函数(这非常关键)。
有没有办法在D中实现这个目标?
C ++中的示例(未经测试,未编译...仅用于说明)。
class Radio{
public:
Radio( std::string id, Station defaultStation, RxChip chip)
:defaultStation(defaultStation),
id(id),
chip(chip){
}
void turnOn() {
log.trace("Radio turned on: id:[%s]", id.c_str());
doEnableRx();
doPostEnable();
setToStation(defaultStation);
}
void turnOff(){
log.trace("Radio turned off: id:[%s]", id.c_str());
doDisableRx();
doPowerOff();
}
void tune(){
log.trace("Tuning");
findAllStations();
}
void setToStation(Station target){
logStationChange(target);
doSetRxChipPassFilter(target);
}
void setChip(RxChip chip) {
rxChip = chip;
}
RxChip getChip() {
return rxChip;
}
private:
// doesn't start with "do" as this is considered a "normal" virtual function.
virtual void findAllStations(){
chip.setFrequency(chip.getLowFreq());
setChipToNextTunedPoint();
Station stat( chip.getFrequency(), tunedStations.size() );
tunedStations.push_back(stat);
}
virtual bool setChipToNextTunedPoint() {
if(chip.isTuned()) {
while( isTuned && chip.getFrequency() < chip.getHighFreq() )
chip.incrementFreq();
}
while( !chip.isTuned() && chip.getFrequency() < chip.getHighFreq() )
chip.incrementFreq();
return chip.isTuned();
}
// "do" functions are considered mandatory extension points for sub-classes
virtual void doEnableRx() = 0;
virtual void doPostEnable() = 0;
virtual void doDisableRx() = 0;
virtual void doPowerOff() = 0;
virtual void doSetRxChipPassFilter(Station target) = 0
{
//default implementation but it must be specified for use by sub-class.
chip.setFrequency(target.getLowFreq());
while( !chip.isTuned() && chip.getFrequency() < station.getHighFreq() ) {
chip.incrementFreq();
}
}
Station defaultStation;
std::vector<Station> tunedStations;
RxChip chip;
}
答案 0 :(得分:2)
不确定。对于非虚拟成员函数,要么使它成为final
(因此编译器可以优化其虚拟性),或者将其模板化,然后保证它是非虚拟的,因为模板函数永远不会虚拟。为了模板化没有模板参数的函数,只需给它一个空的模板参数列表。 e.g。
void setChip(RxChip chip) {...}
变为
void setChip()(RxChip chip) {...}
对于虚拟功能,只需将其设为protected
即可。目前,private
和package
从不是虚拟的,因此如果您希望功能是虚拟的,则需要将其设为public
或protected
,并通过制作protected
,公共API无法访问它。你不能像C ++一样全力以赴地制作private
,但可以说,无论如何,这并不能真正为你买任何东西,因为这个重写的功能仍然可以被班级调用因此,所有让它成为private
的人所做的就是让你无法调用基类版本(无论如何通常都是纯虚拟/抽象)。
但是,我要指出,如果你想要的只是契约,那么D in
和out
块支持多态。所以,你可能甚至不需要NVI。那时,您只需要基类功能具有in
和out
块,其中包含您想要的合同和合同中的任何内容,并且当派生函数被调用时它们将被调用被叫。这只适用于你想要的前置条件和后置条件的断言,但在某些情况下它不需要NVI。