Java 为什么受保护的成员变量被视为反模式,应该用私有访问字段替换?

Java 为什么受保护的成员变量被视为反模式,应该用私有访问字段替换?,java,inheritance,design-patterns,Java,Inheritance,Design Patterns,最近有人建议我将基类中所有受保护的成员变量更改为私有访问 | Class | Package | Subclass | World ————————————+———————+—————————+——————————+——————— protected | y | y | y | n ————————————+———————+—————————+——————————+——————— private | y |

最近有人建议我将基类中所有受保护的成员变量更改为私有访问

            | Class | Package | Subclass | World
————————————+———————+—————————+——————————+———————
protected   |  y    |    y    |    y     |   n
————————————+———————+—————————+——————————+———————
private     |  y    |    n    |    n     |   n
但就实际使用而言,我想到的唯一优势是能够为它们提供单独的读、写和读/写访问权限,以防止误用。下面的Java代码详细介绍了这种用法

public class BaseClass {
    protected Object protectedMember;

    private Object privateMemberR;
    private Object privateMemberW;
    private Object privateMemberRW;

    public BaseClass() {

    } 

    protected final Object getPrivateMemberR(Object obj){
        return privateMemberR;
    }

    protected final void setPrivateMemberW(Object obj){
        privateMemberW = obj;
    }

    protected final Object getPrivateMemberRW(Object obj){
        return privateMemberRW;
    }

    protected final void setPrivateMemberRW(Object obj){
         privateMemberRW = obj;
    }
}
也许并不总是需要将它们声明为final,只是为了确保它们不会被覆盖和滥用

我读过类似的论点,但如果我能避开私有成员变量,我会首先将它们私有化

此外,由于至少在Java中,覆盖方法的访问修饰符只能比超类方法允许更多(而不是更少)的访问,因此您仍然需要在子类中拖动受保护的成员变量或受保护的getter和setter

我没有考虑过多重继承,因为Java不允许多重继承,但我仍然不知道如何使用getter和setter的标准符号来避免遇到问题


就实际使用而言,还有其他实际好处吗(除了它看起来更漂亮、更容易阅读,神奇地希望你通过用getter和setter替换直接引用来防止不正确的使用)

这实际上取决于上下文。这更多的是一个偏好问题,取决于你的设计

例如,您知道private和protected之间的唯一区别是子类和包访问

            | Class | Package | Subclass | World
————————————+———————+—————————+——————————+———————
protected   |  y    |    y    |    y     |   n
————————————+———————+—————————+——————————+———————
private     |  y    |    n    |    n     |   n
它似乎“更容易编码”,因为子类可以直接访问受保护的字段,而不是使用方法访问超类中的私有字段,但这可能会破坏其目的

您必须检查您的继承,并确保在使用受保护时不会出现任何漏洞。例如,直接访问子类

private:某些人可能无法对您的实现执行他们想要的操作

其他人:有人可能会在您的实现中做一些您确实不希望他们做的事情


在我看来,需要有一个特殊的原因来解释为什么你会让一些东西比私人的更容易获得…

这要看情况而定。在不知道子类能够访问字段的具体原因的情况下,很难讨论合适的保护级别

决策中的一个重要因素是类是否用于子类化;如果它没有明确设计为可扩展的,那么保持其内部工作私有是一个合理的默认选择

当类打算被子类化,并且子类需要对基类进行一些控制时,它会变得很麻烦

如果子类显然需要读取和写入字段,那么私有字段的受保护getter/setter可以为您带来的好处是:

a、 )在不当使用发生时(而不是之后)验证和响应不当使用的可能性(例如,通过投掷)。这可以节省大量时间,避免在某一点上字段被不正确地修改,从而在以后的不相关的地方导致问题

b、 )在不需要更改现有子类的情况下更改字段表示的灵活性。我认为这是一个相当罕见的案例;如果字段类型可以更改,并且子类与基类紧密关联,那么您不太可能仅通过在getter/setter中转换表示就成功了

c、 )如果子类只需要读取一个字段,那么很明显 仅提供一个getter就可以防止子类更改该字段。没有可用的设定者明确表示此成员不打算更改。如果可能的话,将字段设置为final可以替代提供受保护的getter

还有一种选择:包私有访问

这是一个经常被忽视的选择。在许多情况下,您需要一个基类提供最通用的实现,然后是用户可以从中扩展的两个或多个变体。变体需要访问基类成员,但用户派生的子类不应该访问。那么包private就是这个工作的工具