对象设计的抽象

时间:2012-02-27 11:08:53

标签: c++

如果我们只在超类中使用受保护和私有访问修饰符,继承如何破坏封装?

有时声称继承暴露了超类实现。如果成员变量被声明为私有,那肯定不是这样吗?如果这指的是在超类中进行的更改会破坏子类,那么这也会影响非继承吗?

关于暴露底层实现,我也没有看到组合是如何有所不同的?我们只能使用组合方法来使用公共函数 - 这肯定会暴露更多?

3 个答案:

答案 0 :(得分:3)

派生类可以访问基类的部分实现。例如。如果您对基类中的任何或所有成员使用protected,那么基类将自己无法强制执行它自己的不变量。这可能会破坏基类的功能。更改字段的名称或删除或添加字段名称可能会导致派生类出现问题,除非它们是私有的,因此再次暴露实现可能会破坏其他正确的代码。

模板模式是公开部分基类实现的有意方式,它的故意并不意味着它不暴露(部分)实现。使用组合(策略)来获得相同的结果(通常与开放/封闭原则相关)具有更松散的耦合。 例如。如果更改其中一个虚拟方法的签名(例如名称)或添加模板模式中使用的新(抽象)方法,则将级联更改为所有派生类。在合成的情况下,您可以更改进行合成的类中所有方法的名称,而无需更改您编写的任何类。您还可以向算法添加另一个步骤而不更改其他类(只要您编写的其中一个部分已经支持此功能)

一种不同的方式来查看虚拟方法可以打破封装的原因:

参加本课程

class ArrayPrinter{
   private bool CanContinue<T>(T[] array, int newIndex){
      return newIndex<array.Length;
   }

   public void Print<T>(T[] array){
      for(var i = 0;CanContinue(array,i);i++){
         Console.WriteLine(string.Format("{0}",array[i]);
      }
   }
}

在上面的例子中,我们可以确定Print的实现不会导致索引超出范围(线程安全除外)并且将打印数组的所有元素(除非Console.WriteLine或string.Fromat失败) )。但是,如果我们将CanContinue的签名更改为以下

   protected virtual bool CanContinue<T>(t[] array, int newIndex)

不再有任何关于ArrayPrinter正常工作的保证。我们已经可以从类外部更改Print的实现,因此破坏了封装。如果你暴露你的领域,SOme可能会争辩你只打破封装。我并不赞同下面的代码,下面的代码遇到了与上面完全相同的问题,尽管它暴露了一个字段(通过一个属性,只是为了表明隐藏你的属性背后的字段并不是&和“确保你没有破坏封装”

class ArrayPrinter<T>{
   private Func<T[],int,bool> _canContinue;
   protected Func<T[],int,bool> CanContinue{
           get{
               return _canContinue ?? canContinue;
           }
           set{
                _canContinue = value;
           }
   }
   private bool canContinue(T[] array, int newIndex){
      return newIndex<array.Length;
   }

   public void Print<T>(T[] array){
      for(var i = 0;CanContinue(array,i);i++){
         Console.WriteLine(string.Format("{0}",array[i]);
      }
   }
}

答案 1 :(得分:1)

继承不会破坏封装,因为在这种情况下也会在SOLID pricniples中说明你应该看一下打开/关闭原则:

开放/封闭原则(OCP)声明类应该为扩展打开但是关闭以进行修改。 “打开扩展”意味着您应该设计类,以便在生成新需求时添加新功能。 “关闭以进行修改”意味着一旦你开发了一个类,你就不应该修改它,除了纠正错误。

更多信息:http://www.blackwasp.co.uk/SOLIDPrinciples.aspx

答案 2 :(得分:-2)

访问修饰符有时是不必要的。如果您正在使用OOP编写一个小应用程序,那么唯一的编码器就是您自己,那么您只需使用公共访问修饰符。

如果您想让自己的代码更清晰,您可以与他人分享您的代码,并且您想告诉他们某些方法或成员变量需要不同的处理方法,然后使用受保护或私有访问修饰符。

我认为被这些问题搞糊涂是没有好处的。在一些新的编程语言中,它不需要使用访问修饰符。