【问题标题】:Prohibit direct extension of Java class outside its package禁止在包外直接扩展 Java 类
【发布时间】:2010-10-18 07:32:53
【问题描述】:

我有一个包裹

public abstract class Player { /*...*/ }

还有这些

public abstract class GamePlayer extends Player { /*...*/ }
public abstract class TournamentPlayer extends Player { /*...*/ }
public abstract class StatelessPlayer extends Player { /*...*/ }

包的用户需要播放器,但为了在不破坏它的情况下使用包,我要求他们永远不要直接扩展播放器。相反,它们应该扩展提供的子类之一。

问题:如何防止用户直接扩展 Player?

我正在寻找一种方法来明确表明该禁令是有意的。

【问题讨论】:

    标签: java inheritance api-design


    【解决方案1】:

    使用默认访问修饰符,也称为“包私有”访问。换句话说,不要指定访问修饰符

    abstract class Player { /*...*/ }
    

    documentation here at Sun's website 更详细地描述了所有访问修饰符。

    【讨论】:

    • 但是客户甚至可以看到课程吗?抱歉,我没有方便的 javac 来检查自己。
    • 不,他们不会 - 这就是为什么它应该只是非公开的构造函数。
    • 另一种可能是公共接口,结合包私有抽象基类...
    • 嗯,Jon Skeet 是正确的,因为我下意识地回答说,没有意识到课程仍然需要公开。 Alnitak的建议也不错。
    【解决方案2】:

    使Player 中的构造函数仅具有包访问权限。然后他们将无法调用构造函数或自己扩展它。如果您在Player 中还没有显式构造函数,请创建一个(否则编译器将创建一个默认的公共无参数构造函数)。

    (请注意,我只建议对构造函数这样做。类本身可以是公共的,以便客户端仍然可以使用它。)

    这是因为任何构造函数(java.lang.Object 除外)都必须调用超类构造函数(显式或隐式)。如果没有可访问的构造函数,则无法创建子类。

    【讨论】:

    • +1 关于隐式公共默认构造函数的注释
    【解决方案3】:

    确保 Player 的构造函数不公开:

    public abstract class Player {
        Player() {
            // initialization goes here
        }
    }
    

    然后类可以从同一个包内扩展 Player,但不能从包外扩展。

    【讨论】:

      【解决方案4】:

      嗯...让 Player 类不公开?省略“public”,它将是包私有的,即只有同一个包中的类可以扩展它。

      但是,没有什么能完全阻止人们将自己的类放入该包中。我相信可以通过将其放入已签名的 JAR 中来防止它,然后在同一个包中加载未签名(或不同签名)类的任何尝试都将失败。

      【讨论】:

      • 我相信这可以防止在包之外使用,而不仅仅是继承。
      【解决方案5】:

      推荐

      • 为您希望客户访问但不创建或子类化的事物创建公共接口
      • 为您希望客户访问的事物创建公共类创建或子类化
      • 其他任何内容都应该是非公开的

      这种方法的问题在于,您最终需要将所有内容都放在一个包中,随着图书馆的发展,这对组织不利。

      要允许使用多个受保护的包,请查看 OSGi。

      OSGi 允许您限制捆绑包 (jar) 允许其他捆绑包访问的包,甚至设置允许额外可见性的“朋友”捆绑包。

      当您真的想保护变得很大的库时,Java 的包即保护单元模型是不够的......

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-30
        • 2021-12-08
        相关资源
        最近更新 更多