What is the point of Auto-Implemented Properties?
例如,C中自动实现的属性的一个例子是:
1
| public double TotalPurchases { get; set; } |
我理解它们是什么,正如他们所说,"编译器创建了一个私有字段,只能通过get和set访问该字段。"
我的问题是这有什么意义?
我的意思是,在其他语言中,重点是:你有一个变量,你把它设为私有的,然后你声明一些公共的函数,你可以通过它访问这个变量,而不是直接访问。为什么?好吧,因为你可以按照你想要的方式实现这个"变量",而你的类的用户对此一无所知,所以他只是得到并设置他看到的是类的一个属性。
但是在这里,尽管您有一个只能通过get和set访问的私有变量(如上所述),但您也有一个非常公共的变量,实际上您可以直接访问它,这就破坏了get和set的初衷。
我的意思是如果你想
1
| cust1.TotalPurchases += 499.99; |
为什么不
1
| public double TotalPurchases; |
完成了吗??
编辑:这个问题已被标记为"可能的副本",在我看来不是,我将尝试用我相当有限的英语解释为什么不是。
"可能的副本"的作者最初写了一种破坏完全封装的方法。后来他承认他"不能忍受写这么多",所以他只是使用公共领域。毕竟,他一开始并不关心封装。
我的职位完全相反。我想保持封装,因为正如我之前解释的那样,这给了我自由实现我认为合适的totalpurchases。我可以使用一个变量,但我可以从数据库中得到它,或者通过神经网络计算它。问题是我不希望用户对此视而不见。
但是,如果必须按照说明使用get和set,那么就必须声明一个公共变量,对吗?或者如果我这样做
1
| private double TotalPurchases {get; set;} |
这些是公开的吗?我怀疑他们不是。
所以我的问题是,破坏封装有什么意义?
- 您不直接访问它,而是通过getter和setter访问它,并且这些可以以您认为合适的任何方式实现。对客户机来说,字段和属性似乎是相同的,是的。如果这是不需要的(例如,因为getter和setter非常昂贵),那么不要使用属性,使用显式方法。
- private double TotalPurchases {get; set;}创建了一个具有非公共getter和setter的私有财产。所以这在外面根本看不见。关于auto-properties的要点是,您拥有一个属性,而不必亲自执行管理私有支持字段的所有样板工作。您使用的是属性而不是字段,因为这样可以在以后更改实现,而不会破坏合同。–所有这些都在相关问题中进行了解释。我也不明白你所说的"破坏封装点"是什么意思。
- @当您说"稍后更改实现"时戳一下,这是否意味着我可以做一些类似于public double TotalPurchases{ get{//domystuff};set{//domystufftoo}}的事情。我是说,否则我以后就不知道这些了
- 是的,从自动属性切换到您自己的实现,在那里您可以做任何事情(获取/设置字段中的值、查询数据库、WebService、抛出骰子等),这并不是对合同的一个破坏性更改。在外部,它仍然是一个属性,并且从外部看不到实现。
- public TotalPurchases并不总是public TotalPurchases {get; set;}的替代品,例如,请参阅stackoverflow.com/a/19851801/34092-不是说此功能只适用于属性。这是一个自动实现的属性可以工作但字段不能工作的示例。
从字段更改为属性对于库来说是一个突破性的更改,因为访问字段的CIL与访问属性的CIL不同。如果您想在编写库时获得属性的好处(也就是说,您可以将自动合成的getter/setter替换为执行其他操作的getter/setter),而不需要重新构建世界,那么您需要为其规划并使用{ get; set; }语法。
正如人们在评论中已经概述的那样,反思也有一些不同,但它们通常不是你想做的事情,也不是你想做的事情。
- 所以,我理解的是,既然将来我可以更改get/set的实现,那么现在就应该编写自动合成的get/set了吗?它不是破坏了封装吗?
- @Kansairobot,到底是什么破坏了封装?
- 在我的示例中,用户可以看到一个名为totalpurchases的变量……难道他没有看到这个变量,只能使用getpurchases或setpurchases进行交互吗?
- @Kansairobot,我还是不确定你要把这个带到哪里去。你是说属性不是正确的封装,因为它们不是方法吗?
- 也许是我学得不好。有人告诉我,不要让用户直接设置一个对象变量。把它们变成私人的。如果用户想要访问它们,他们应该使用方法。这样,只要get-set方法行为不变,我就可以用该变量做任何我想做的事情。
- @Kansairobot,你教过obj.Foo = 4的语法是邪恶的吗?您可能会意识到,任何可以放在SetFoo方法中的东西也可以在属性的set { ... }块中找到它的方法。如果让同一代码运行的两种语法上不同的方法只是一个问题,我不认为这会困扰任何人。
- 拥有一个字段而不是一个属性会使事情有所不同。访问属性的已编译代码与调用方法的已编译代码相同。但是,访问字段的编译代码是不同的,如果您需要进行任何与二进制兼容的更改,它不允许您有任何空闲空间。