我认为对此没有语言不可知的答案,因为构成“财产”的是一个特定语言的问题,而“财产”的调用者所期望的也是一个特定于语言的问题。我确实认为思考这一问题的最富有成果的方法是从呼叫者的角度考虑它的外观。
在C#中,属性的区别在于(通常)使用大写字母(如方法),但没有括号(如公共实例变量)。如果您看到以下代码,没有文档,您期望得到什么?
var reciprocalHeading = myHeading.Reciprocal;
作为C#的相对新手,但我读过Microsoft的《财产使用指南》,因此,我希望Reciprocal
能:
- 成为
Heading
该类的逻辑数据成员
- 通话费用低廉,因此我无需缓存价值
- 缺乏明显的副作用
- 如果连续调用两次,将产生相同的结果
- (也许)提供一个
ReciprocalChanged
活动
在这些假设中,(3)和(4)可能是正确的(假设Heading
是一个不变的值类型,如Ewan的回答所示),(1)可争论,(2)未知但也可争论,(5)具有语义上的意义(尽管具有标题的任何事物都应该具有HeadingChanged
事件)。这向我表明,在C#API中,“获取或计算倒数”不应被实现为属性,但是特别是如果计算便宜且不Heading
可变,这是一个临界情况。
(但是请注意,所有这些问题都与调用属性是否创建新实例无关,甚至与(2)也没有关系。在CLR中创建对象本身并不昂贵。)
在Java中,属性是方法命名约定。如果我看到
Heading reciprocalHeading = myHeading.getReciprocal();
我的期望与上面的期望相似(如果未明确列出):我希望此调用便宜,等幂且没有副作用。但是,在JavaBeans框架之外,“属性”的概念在Java中并不是那么有意义,尤其是当考虑不带对应属性的不可变属性时setReciprocal()
,getXXX()
约定现在有点过时了。从有效Java的第二版(至今已有八年历史了):
返回boolean
调用对象的非功能或属性的方法通常以名词,名词短语或以动词get
… 开头的动词短语来命名。有一个声音特遣队声称只有第三种形式(以开头get
)是可以接受的,但是这种主张没有任何依据。前两种形式通常会导致代码更具可读性……(第239页)
那么,我希望在一个当代的,更流畅的API中
Heading reciprocalHeading = myHeading.reciprocal();
-这再次表明该调用便宜,等幂且没有副作用,但是对于执行新的计算还是创建新的对象一无所知。这可以; 在一个好的API中,我不在乎。
在Ruby中,没有属性。有“属性”,但如果我看到
reciprocalHeading = my_heading.reciprocal
我无法立即知道我是@reciprocal
通过attr_reader
还是简单的访问器方法来访问实例变量,或者是否正在调用执行昂贵计算的方法。方法名称是一个简单名词的事实calcReciprocal
再次表明,该调用至少便宜,并且可能没有副作用,这一事实而不是说出。
在Scala中,命名约定是具有副作用的方法带有括号,而没有副作用的方法则不带括号,但是
val reciprocal = heading.reciprocal
可以是以下任何一种:
// immutable public value initialized at creation time
val reciprocal: Heading = …
// immutable public value initialized on first use
lazy val reciprocal: Heading = …
// public method, probably recalculating on each invocation
def reciprocal: Heading = …
// as above, with parentheses that, by convention, the caller
// should only omit if they know the method has no side effects
def reciprocal(): Heading = …
(请注意,Scala 允许样式指南不鼓励的各种操作。这是我对Scala的主要厌烦之一。)
没有括号告诉我这个电话没有副作用。该名称再次表明该呼叫应该相对便宜。除此之外,我不在乎它如何为我带来价值。
简而言之:了解您使用的语言,并了解其他程序员会对您的API带来什么期望。其他所有内容都是实现细节。
Heading
不如说是一成不变的类型并reciprocal
返回一个新值,这Heading
是“成功的秘诀”。(需要注意的两个调用reciprocal
应该返回“同一件事”,即它们应该通过相等性测试。)