带你撸出一手好代码
「自封装字段」编程模式

使用类封装代码的一点指导原则:类的数据字段使用private关键字修饰,防止类外部的代码对它的访问, 如果类外部的代码需要访问字段的数据,需要通过类对外公开的getter/setter方法进行。

 

    public class Foo
    {
        private  int field;
 
        public Foo(int field)  {
            this.field = field;
        }
 
        public int getField() {
            return field;
        }
    }

 

在类外部, 无法直接访问到field字段, 需要通过 getField方法间接的获取field字段的数据。 这种方式也称为「信息隐藏」,类外部的代码对于类内部的数据字段结构是未知的, 这能防止类外部代码对类内部数据进行肆无忌惮的修改,导致出现不可控的意外发生和类外部代码对类内部结构过多的依赖。

 

但是在类内部的各个方法中可以随意的访问类内部的字段数据, 因为只要对字段数据的访问被限制在一个类内, 问题相对还是在可以控制范围之内的。

 

  public class Foo
    {
        private int field;
 
        public Foo(int field)  {
            this.field = field;
        }
 
        public int getField() {
            return field;
        }
 
        public void printField()  {
            System.out.println(this.field);
        }
    }

 

如这里的用来打印field字段值的printField方法便是直接访问field字段。

 

然而,对于类数据字段访问还存在一种更加谨慎的模式,即使在类内部也推荐使用getter/setter方法而不是字段本身。

 

        public void printField()  {
            System.out.println(this.getField());
        }

 

这种方法称之为「自封装字段」

 

在类的内部访问数据还要通过方法似乎有点矫枉过正了,然而也并不是完全没有好处。

 

子类继承父类,父类的代码是通过方法访问数据字段,当子类重写这个方法,效果也同时能反应至父类。

 

public class Main {
    public static class Foo
    {
        private int field;
 
        public Foo(int field)  {
            this.field = field;
        }
 
        public int getField() {
            return field;
        }
 
        public void printField()  {
            System.out.println(this.getField());
        }
    }
 
    public static class SubClass extends Foo{
        public SubClass(int field ) {
            super(field);
        }
 
        @Override
        public int getField() {
            return super.getField() / 2;
        }
    }
 
    public static void main(String[] arg) throws InterruptedException {
        Foo foo = new SubClass(100);
        foo.printField(); //result 50
    }
}

 

子类重写父类的getter/setter方法后,父类使用getter/setter方法的代码即便不做任何改动也能得到预料之中的结果,而通过直接访问类的数据字段是做不到的。与此同时,这也算是设计模式中的「模板方法」的一种变体。

 

总而言之,在类内部使用类数据是直接访问数据字段还是通过getter/setter方法访问并没有优劣之分,也没有可以直接套用的模板,选择何种方式要根据代码的实际情况权衡。


作者:陈大侠
日期:2018-02-03

留言(0条)

我要发表留言

您的大名 选填
电子邮箱 选填

欢迎关注微信公众号 「带你撸出一手好代码」

首页    GitHub 知乎 豆瓣 博客园