我有一个关于面向对象访问说明符的原因的一般问题.我从来没有完全理解为什么它们存在的原因,只是认为它们是作为一种非常基本的代码安全形式存在但是在查看了这个线程的讨论之后
我知道我完全错了,他们根本没有帮助安全.那些访问说明符只是被认为是面向对象设计中的良好编程实践吗?当我们说私人或受保护时,究竟是谁保护数据字段或类或方法?人们是否仍然可以访问已经知道它的方法?通过反思等方法?
我很抱歉,如果这个问题看起来很基本或有点元抄袭,但它总是困扰我,我不太清楚其中一个主要的OOP封装概念的确切推理.
访问修饰符用于指示您打算如何使用您的代码.当你保持内部状态时,它们尤为重要.考虑一个保持计数的类:
public class Thing {
public int count = 0;
public void doSomething() { count++; }
public int getHowManyTimesDone() { return count; }
}
Run Code Online (Sandbox Code Playgroud)
这段代码有什么问题?如果调用者修改count,我的代码违反了其合同:
Thing x = new Thing();
x.doSomething();
x.doSomething();
x.count = 0;
System.out.println(x.getHowManyTimesDone());
Run Code Online (Sandbox Code Playgroud)
我的班级合同说这应该打印2,但它会打印,0因为调用者修改了count.通过制作count一个private变量,我告诉来电者,"嘿,你不应该碰这个!这样做可能会让这个代码破解!"
Python没有隐私概念.相反,按照惯例,前缀为变量的单个下划线向调用者提供相同的警告:"如果触摸它,它可能会破坏此代码!" 这可能是最类似的protected.双下划线也会触发名称修改,这表明即使是子类也不应该使用它; 这将是最类似的private.在Python中,如果他们无论如何都要访问这些成员,那么调用者有责任接受风险,但鼓励程序员尽可能公开.
至于谁在Java中实现变量的可见性,那就是运行时本身.尽管如此,确实有一些聪明的方法.我相信反射提供了一些手段,任何进入字节码或JVM本身的人都可以做些什么.考虑一下模拟做的事情; 他们可以说服JVM模拟是一种特殊的类型,即使它不是.
还有一件事.在Java中,鼓励程序员保留所有实例变量private并使用方法来访问和改变它们.这是为了可维护性,而不是隐藏细节的哲学原因.由于Java没有C#或类似Python的属性机制,如果需要在获取或设置实例变量时添加逻辑,则需要修改依赖于该实例变量的所有代码以使用这些方法.通过始终使用方法来访问变量,可以最大限度地减少通过进行此类更改而中断的相关代码.换句话说,它是处理语言缺点的一个障碍.