美文网首页
why use getter,setter/accessor?

why use getter,setter/accessor?

作者: 地坛公园 | 来源:发表于2018-09-09 02:17 被阅读0次

    这是最近在想的一个问题,使用getter,setter的好处是什么? 但实际上,我在搜索的过程中,看到了很多“反对”的声音。

    先复习一下,什么是getter,setter.

    在C#中,我们又称它为property(属性),它是一组setter,getter的访问器(accessor),是一个函数成员。
    在使用上,就像是在调用公共的字段一样,但它是函数,不分配内存。

    set访问器为属性赋值。拥有一个单独的,隐式的值参,名为value,与属性的类型相同。返回类型为void.
    get访问器从属性获取值。没有参数,拥有一个与属性类型相同的返回类型。get访问器返回一条return语句。
    setter,getter可以任意顺序声明,并且,除了这两个访问器外,不允许有其它的方法。

    如:

    private stringcristiano;
        public string Cristinao{
            set{ cristiano = value; }
            get{ return cristiano; }
            age{...}//error
        }
    
    属性常和字段进行关联,字段通常设置为private(这通常叫”后备字段“),因为面向对象的设计的重要原则之一就是数据封装,意味着类型的字段永远不应该被公开,否则很容易被不恰当的使用字段而破坏了对象的状态,如:xxx.age-=5;是不合理的,所以,要通过函数,来对保护的字段进行读写。(很像代理设计模式:))

    在属性中,可以做很多逻辑上的计算,比如:

    private int money;
        public int Money{
            set{ 
                money = value < 100 ? 100 : value;
            }
            get{
                return money < 100 ? 100 : money;
            }
        }
    

    属性始终是函数成员。

    getter,setter并不需要同时定义,只包含getter的属性,只能读取,而不能写入,相反,只包含setter的属性,只能写入,不能读取,但两者必须至少定义一个。

    自动实现属性

    因为属性经常被关联到”后备字段“,C#提供了自动实现属性(AIP),允许只声明 属性 而不需要声明 后备字段
    ,编译器会为你隐藏的创建一个私有的字段,并且自动挂接到get和set访问器上(accessor)

    如:

    public string Messi {
            set;
            get;
        }
    
    如果其中一个访问器提供了方法体,另一个也需要。
    public static string Russia {
            set;
            get;
        }
    
    什么时候应该使用字段?

    1.你希望返回字段来执行一些其它的副作用,比如缓存某个值(currentState,PreviousState)
    2.你希望以线程安全的方式来访问字段
    3.这是一个逻辑的字段,需要计算来获得,如面积area.

    基础说完了,那么以上面定义的Russia为例,他和常规定义一个set,get函数有什么优势呢?

    private string russia;
        public void SetRussia(string val)
        {
            russia = val;
        }
    
        public string GetRussia()
        {
            return russia;
        }
    

    首先:

    最直观的是属性/访问器比常规函数,代码上更加的简洁了,无论是定义上,还是使用上。

    但仅仅就是这些吗,所以常规操作,去stackoverflow上找找大神们的回复,但意外的是,有很多人抨击accessor的设计是evil.有兴趣可以看下面的链接:
    https://www.javaworld.com/article/2073723/core-java/why-getter-and-setter-methods-are-evil.html

    CLR via C#的作者也对accessor的设计嗤之以鼻,不过他提到AIP自动属性无法调试和序列化&反序列化是不准确的,也许和他的应用环境有关,我在Mono里测试,都是OK的:)

    具体关于getter,setter的讨论可以看这篇(很精彩):
    https://stackoverflow.com/questions/1568091/why-use-getters-and-setters-accessors

    有的人说,setter/getter,让代码不易于阅读,你无法直接判断是共公的字段还是属性。
    使用常规自定义的setxx/getxxx,具有更好的移植性。

    属性/访问器,除了在使用和定义上,相比常规函数要更简洁以外,它通常于需要做一些额外操作的情况,比如校验,保存旧的值,做一些逻辑上的计算等等,如果仅仅是返回源引用的形式,意义并不大。大多数情况下,我们还是要使用自定义参数的函数来适应各种复杂的场景。(2018.9.10 更新)

    参考资料:
    C#图解教程
    CLR via C#

    写得有些仓促,后面看到相关的会继续补充上来,2点15分了,时间过得太快,肚子又饿了,一堆任务压着没有完成,现在休息,早起继续工作!

    相关文章

      网友评论

          本文标题:why use getter,setter/accessor?

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