美文网首页java基础
Java封装——访问权限控制

Java封装——访问权限控制

作者: 冰糖雪梨葫芦甜 | 来源:发表于2018-11-19 22:18 被阅读0次

    预备术语

    若将程序开发人员按照角色分类,可以分为以下两类:

    类创建者

    那些创建新数据类型的程序员。

    客户端程序员

    那些在其应用中使用类创建者提供的数据类型的类消费者。
    注:客户端程序员也可以是类创建者:他在类库的设计中用到了其他程序员创建的类,同时他也将提供新的数据类型给其他类消费者。

    前言

    通常一个优秀的作者可能会反复的修改其作品,以使得其著作越来越完美(没有绝对的完美,希望读者不要纠结于完美这个用词),这也是为什么很多著作都会有第一版、第二版、第三版等等。
    同理,一个优秀的类设计者也需要反复的修改他所创建的类,使其越来越完美。然而,有时类创建者的修改,对于一些客户端程序员可能是一场灾难。
    例如,这些类消费者在其应用中大量的使用到了类的某个(或某些)方法,而类创建者在某次更新版本后声明:以前的那个方法存在极大的缺陷,现已增加了一个全新的方法替代了那个方法(甚至可能以前的方法直接被删除了),新的方法不仅避免了缺陷,更极大的提升了效率。

    以下代码展示了一个具体的例子:
    注:“//:”表示一个文件的开头,“//:~”表示这个文件的结尾。因此,以下代码可能不止在一个文件中。

    //: Design.java —— 类设计者创建的类(新版)
    public class Design {
        // 旧的有缺陷的方法
        void method() {
            //some code...
        }
        // 新的避免缺陷且更有用的方法
        void moreUserful() {
            //some code...
        }
    }
    //:~
    
    //: App.java —— 客户端程序员创建的应用(大量使用了旧版的方法)
    public class App {
        public static void main(String[] args) {
            //some code...
            Design d1 = new Design();
            Design d2 = new Design();
            Design d3 = new Design();
            d1.method();
            d2.method();
            d3.method();
            //some code...
        }
    }
    //:~
    

    那么此时,这些客户端程序员该怎么做呢?
    一,继续使用老版本的类,同时承受缺陷所带来的所有风险(这在多数情况下显然是不明智的)。
    二,使用新版本的类,并把应用中所有的旧版方法修改为新版中新增的方法,根据应用大小,修改成百上千甚至上万的方法,都是有可能的(好吧,可能某位负责任的程序员在把所有方法都修改好后就直接下岗,并决定再也不从事该行业了)。
    显然,无论哪个选择,都不是那么令人满意。
    实际上,这是一个设计时的缺陷。一个合理的解决方案是:类创建者在设计时专门对外提供一个方法供类消费者使用,这个方法调用了任何随时可能修改的其它方法。并且跟类消费者约定好:只能用这个对外提供的方法,其它方法不要使用。

    以下代码展示了改进的例子,以及在这个例子中类创建者的更改对客户端程序员的影响。

    //: SmarterDesign.java —— 类设计者创建的类(新版)
    public class SmarterDesign {
        // 约定好的对外提供的方法
        void provide() {
            // method();
            /* 在新版中注释掉了旧版调用了方法,
             * 使用了新的更可靠的方法,然而此时
             * 只要客户端程序员遵守约定,是不会
             * 对其原来的代码产生影响的:
             * 他们不需要修改任何原来的代码就能
             * 享有新版的特性,只需要将SmarterDesign
             * 文件替换为新版即可。
             */
            moreUseful();
        }
        // 旧的有缺陷的方法
        void method() {
            //some code...
        }
        // 新的避免缺陷且更有用的方法
        void moreUseful() {
            //some code...
        }
    }
    //:~
    
    //: App2.java —— 客户端程序员创建的应用(大量使用了与类创建者约定好的对外提供的方法)
    public class App2 {
        public static void main(String[] args) {
            //some code...
            SmarterDesign d1 = new SmarterDesign();
            SmarterDesign d2 = new SmarterDesign();
            SmarterDesign d3 = new SmarterDesign();
            d1.provide();
            d2.provide();
            d3.provide();
            //some code...
        }
    }
    //:~
    

    可以看到,在这个例子中,只要大家都遵守约定,不管SmarterDesign的创建者以后如何修改provide()中调用的方法,都不会对客户端程序员原先的代码结构产生影响。
    这个设计仍然存在一个问题:设计者的良苦用心是否起效在于使用者是否遵守约定。然而,可能会有某个(甚至某些)客户端程序员并不知道这些约定(可能他们没有仔细看设计者提供的文档),或者在开发的过程中忘了有这么回事,那么可能设计者的好心就白费了。
    好在Java语言中有访问权限修饰词,它们能很好的处理这类问题:只要类创建者合理的使用了它们,那么不管是类创建者还是客户端程序员都不必那么费心了,这些修饰词会替我们好好的处理这些麻烦。

    Java访问权限修饰词

    Java访问权限修饰词在使用时,置于类中每个成员的定义之前。每个访问权限修饰词仅控制它所修饰的特定定义的访问权,以下是各种修饰词所定义的访问权。

    public

    使成员成为公共的成员,无论是谁,无论在哪里,都可以访问该成员。

    默认的包访问权

    本文以上所有示例中的大多数成员都没有使用任何访问权限修饰词,这些成员默认的拥有包访问权,即同一个包中任何地方都能访问到该成员。

    protected

    使成员成为受保护的成员,该成员只有在本类、本类的子类以及同一个包中可以被访问。也就是说,protected修饰的成员同时拥有包访问权。

    private

    使成员成为私有的成员,该成员只有在本类中可以被访问。

    回到问题

    让我们回顾之前SmarterDesign的例子,利用修饰词,类创建者只需将需要对外提供的成员修饰为public的(例子中的provide()),将需要隐藏的实现修饰为private的(例子中的method()和moreUseful()),即可避免以后修改(甚至是删除)隐藏的实现对客户端程序员的代码结构造成影响。

    *练习

    请读者尝试给SmarterDesign例子中的成员添加合适的修饰词,来达到类设计者预期的效果(相信这对您而言并不是一件难事)。

    相关文章

      网友评论

        本文标题:Java封装——访问权限控制

        本文链接:https://www.haomeiwen.com/subject/hktzfqtx.html