如果我们只在超类中使用受保护和私有访问修饰符,继承如何破坏封装?
有时声称继承暴露了超类实现。如果成员变量被声明为私有,那肯定不是这样吗?如果这指的是在超类中进行的更改会破坏子类,那么这也会影响非继承吗?
关于暴露底层实现,我也没有看到组合是如何有所不同的?我们只能使用组合方法来使用公共函数 - 这肯定会暴露更多?
答案 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)声明类应该为扩展打开但是关闭以进行修改。 “打开扩展”意味着您应该设计类,以便在生成新需求时添加新功能。 “关闭以进行修改”意味着一旦你开发了一个类,你就不应该修改它,除了纠正错误。
答案 2 :(得分:-2)
访问修饰符有时是不必要的。如果您正在使用OOP编写一个小应用程序,那么唯一的编码器就是您自己,那么您只需使用公共访问修饰符。
如果您想让自己的代码更清晰,您可以与他人分享您的代码,并且您想告诉他们某些方法或成员变量需要不同的处理方法,然后使用受保护或私有访问修饰符。
我认为被这些问题搞糊涂是没有好处的。在一些新的编程语言中,它不需要使用访问修饰符。