美文网首页
Effective Java 3rd 条目16 在公开类使用访问

Effective Java 3rd 条目16 在公开类使用访问

作者: tigershin | 来源:发表于2018-01-21 17:15 被阅读7次

    偶然地你可能忍不住编写一个退化的类,除了把实例域分组以外不作为任何目的:

    // 像这样的退化的类不应该是公开的! 
    class Point {
        public double x;
        public double y; 
    }
    

    因为这样的类的数据域可以直接访问,所以这些类没有提供封装的优点(条目15)。没有改变API你就不能改变这个表示,你不能实现不变性,而且当访问一个域时你不能采取辅助行动。不妥协的面向对象程序员感觉这种类是诅咒,应该总是用这样的类替代:它有私有域和公开访问子方法(accessor method)(getter),而且有对于可变类的设置方法(mutator)(setter):

    // 通过访问子方法和设置方法的数据封装
    class Point {
        private double x; 
        private double y;
    
        public Point(double x, double y) { 
            this.x = x; this.y = y; 
        }
    
        public double getX() { return x; } 
        public double getY() { return y; }
    
        public void setX(double x) { this.x = x; } 
        public void setY(double y) { this.y = y; }
    }
    

    当然,当涉及到公开类,这些不妥协者是正确的:如果一个类在它的包外是可访问的,那么提供访问子方法来维持改变类内部表示的灵活性。如果一个公开类暴露了它的数据域,那么失去了改变它的表示的所有希望,因为客户端代码可以到处分布。

    然而,如果一个类是包私有的或者是私有嵌套类,那么暴露它的数据域本质上没有什么错误--假设它们能够充分描述由类提供的抽象。相对于访问子方法,这个方法在类声明中和在使用它的客户端代码中有更少的视觉混乱。虽然客户端代码捆绑于类的内部表示,但是这个代码是限制在包含这个类的包中。如果表示中的改变变得迫切,那么你可以执行这个改变,而没有触碰到包外的任何代码。对于私有内嵌类这个情形,这个改变的范围进一步地限制在包含类中。

    Java平台库中的许多类违反了公开类不应该直接暴露域这个建议。显著的例子包括java.awt包中的Point和Dimension类。这些类应该看作警世故事,而不是模仿它们。就像在条目67中描述的一样,暴露Dimension类内部的决定导致了今天仍然困扰我们的严重性能问题。

    虽然直接暴露公开类的域从来都不是一个好主意,但是当域是不可变时它有较低危害。你不能改变这种类的表示而没有改变它的API,而且当域是可读的时候,你不可以采取辅助行动,但是你可以实施不可变性。比如,下面的类保证每个实例代表一个有效的时间:

    // 暴露不可变域的公开方法 - 有问题的 
    public final class Time {
        private static final int HOURS_PER_DAY = 24; 
        private static final int MINUTES_PER_HOUR = 60;
    
        public final int hour; 
        public final int minute;
    
        public Time(int hour, int minute) { 
            if (hour < 0 || hour >= HOURS_PER_DAY) 
                throw new IllegalArgumentException("Hour: " + hour); 
            if (minute < 0 || minute >= MINUTES_PER_HOUR) 
                throw new IllegalArgumentException("Min: " + minute); 
            this.hour = hour; 
            this.minute = minute; 
        } 
        ... // Remainder omitted
    }
    

    概括起来,公开类从不应该暴露可变域。尽管仍然有问题,但是公开类暴露不可变域有较低危害。然而,包私有的或者私有的内嵌类暴露不管可变与不可变的域,有时是合适的。

    相关文章

      网友评论

          本文标题:Effective Java 3rd 条目16 在公开类使用访问

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