inheritance - 私有(private)继承和非虚拟接口(interface)

标签 inheritance d non-virtual-interface

所以我对 D 感兴趣已经有一段时间了,而且不久前我还搞过它。我开始再次审视它,我真的很喜欢它想要实现的目标,但我对我最喜欢的 C++ 设计选项...非虚拟接口(interface)感到疑虑。

我喜欢这种设计的地方在于,它允许在继承层次结构的“顶部”进行前置和后置条件检查、日志记录和资源管理。这允许设计者指定一组相关类的所有公共(public)功能,并将类的可定制部分分解为非常小的函数。它还减少了需要在子类中编写的功能量。另外,由于虚拟扩展点是私有(private)的,因此它不会污染接口(interface),也不会允许用户直接调用特定于实现的函数(这非常关键)。

有没有办法在 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;

}

最佳答案

当然。对于非虚拟成员函数,要么将其设为final(以便编译器可以优化其虚拟性),要么将其模板化,然后保证它是非虚拟的,因为模板函数永远不是虚拟的。为了模板化一个没有模板参数的函数,只需给它一个空的模板参数列表。例如

void setChip(RxChip chip) {...}

变成了

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

对于虚函数,只需将其保护即可。目前,privatepackage 从来都不是虚拟的,因此如果您希望函数是虚拟的,则需要将其设为 publicprotected,并且通过使其成为protected,公共(public) API 无法访问它。你不能像在 C++ 中那样全力以赴地使其成为私有(private)的,但可以说,这并没有真正给你带来任何好处,因为重写函数仍然可以由该类调用因此,将其设置为 private 所做的就是将其设置为使您无法调用基类版本(无论如何,基类版本通常是纯虚拟/抽象的)。

但是,我要指出的是,如果您想要的只是合约,D 的 inout block 支持多态性。因此,您甚至可能不需要 NVI。那时,您只需让基类函数具有 inout block ,其中包含您想要的任何 in 合约和 out 合约,并且当派生函数被调用。这仅适用于您想要的前置条件和后置条件的断言,但在某些情况下不需要 NVI。

关于inheritance - 私有(private)继承和非虚拟接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17444449/

相关文章:

Ruby - 词法范围与继承

c++ - 如何修复由多态性引起的错误?

inheritance - 对象表达式和错误 FS0419 : 'base' values may only be used to make direct calls to the base implementations of overridden members

sockets - 允许 D 应用程序和浏览器之间双向通信的工具链

garbage-collection - d 垃圾收集器和实时应用程序

C#调用接口(interface)方法非虚实现

c# - C# 中的非虚拟方法、静态绑定(bind)和接口(interface)

python - 从子类中的父类访问属性

Fedora 16 上的 D 编程