私有继承和非虚拟接口

时间:2013-07-03 09:32:49

标签: inheritance d non-virtual-interface

所以我现在对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;

}

1 个答案:

答案 0 :(得分:2)

不确定。对于非虚拟成员函数,要么使它成为final(因此编译器可以优化其虚拟性),或者将其模板化,然后保证它是非虚拟的,因为模板函数永远不会虚拟。为了模板化没有模板参数的函数,只需给它一个空的模板参数列表。 e.g。

void setChip(RxChip chip) {...}

变为

void setChip()(RxChip chip) {...}

对于虚拟功能,只需将其设为protected即可。目前,privatepackage从不是虚拟的,因此如果您希望功能是虚拟的,则需要将其设为publicprotected,并通过制作protected,公共API无法访问它。你不能像C ++一样全力以赴地制作private,但可以说,无论如何,这并不能真正为你买任何东西,因为这个重写的功能仍然可以被班级调用因此,所有让它成为private的人所做的就是让你无法调用基类版本(无论如何通常都是纯虚拟/抽象)。

但是,我要指出,如果你想要的只是契约,那么D inout块支持多态。所以,你可能甚至不需要NVI。那时,您只需要基类功能具有inout块,其中包含您想要的合同和合同中的任何内容,并且当派生函数被调用时它们将被调用被叫。这只适用于你想要的前置条件和后置条件的断言,但在某些情况下它不需要NVI。