Non penso che ci sia una risposta agonistica della lingua a questo dato che ciò che costituisce una "proprietà" è una domanda specifica della lingua, e ciò che un chiamante di una "proprietà" si aspetta è una domanda specifica della lingua. Penso che il modo più fruttuoso di pensare a questo sia pensare a come appare dal punto di vista del chiamante.
In C #, le proprietà sono distintive in quanto sono (convenzionalmente) in maiuscolo (come i metodi) ma mancano parentesi (come le variabili di istanza pubbliche). Se vedi il seguente codice, manca la documentazione, cosa ti aspetti?
var reciprocalHeading = myHeading.Reciprocal;
Come novizio relativo di C #, ma uno che ha letto il Proprietà di Microsoft Linee guida per l'utilizzo , mi aspetto che Reciprocal , tra l'altro:
- essere un membro di dati logici della classe
Heading
- essere economico da chiamare, in modo tale che non ci sia bisogno di memorizzare nella cache il valore
- mancano effetti collaterali osservabili
- produce lo stesso risultato se chiamato due volte in successione
- (forse) offre un evento
ReciprocalChanged
Di queste ipotesi, (3) e (4) sono probabilmente corrette (assumendo che Heading sia un tipo di valore immutabile, come in La risposta di Ewan ), (1) è discutibile, (2) è sconosciuta ma anche discutibile, e (5) è improbabile che abbia senso semantico (sebbene qualunque abbia un'intestazione dovrebbe forse avere un evento HeadingChanged ). Questo mi suggerisce che in un'API C #, "ottenere o calcolare il reciproco" dovrebbe non essere implementato come una proprietà, ma soprattutto se il calcolo è economico e Heading è immutabile, è un caso limite.
(Si noti, tuttavia, che nessuno di questi dubbi ha nulla a che fare con la chiamata della proprietà crea una nuova istanza , nemmeno (2). Creazione di oggetti nel CLR, in e di se stesso , è piuttosto economico.)
In Java, le proprietà sono una convenzione di denominazione dei metodi. Se vedo
Heading reciprocalHeading = myHeading.getReciprocal();
le mie aspettative sono simili a quelle sopra (se meno esplicitamente definite): mi aspetto che la chiamata sia economica, idempotente e priva di effetti collaterali. Però,
al di fuori del framework JavaBeans, il concetto di una "proprietà" non è tutto ciò che è significativo in Java, e in particolare quando si considera una proprietà immutabile senza corrispondente setReciprocal() , la convenzione getXXX() è ora un po 'antiquata. Da Efficace Java , seconda edizione ( già più di otto anni ora):
Methods that return a non-boolean function or attribute of the object on which they’re invoked are usually named with a noun, noun phrase, or a verb phrase beginning with the verb get …. There is a vocal contingent that claims that only the third form (beginning with get) is acceptable, but there is little basis for this claim. The first two forms usually lead to more readable code… (p. 239)
In un'API contemporanea e più fluente, quindi, mi aspetto di vedere
Heading reciprocalHeading = myHeading.reciprocal();
- che suggerirebbe ancora una volta che la chiamata è economica, idempotente e priva di effetti collaterali, ma non dirà nulla sul fatto che venga eseguito un nuovo calcolo o che venga creato un nuovo oggetto. Questo va bene; in una buona API, non me ne dovrebbe importare.
In Ruby, non esiste una cosa come una proprietà. Ci sono "attributi", ma se vedo
reciprocalHeading = my_heading.reciprocal
Non ho un modo immediato per sapere se sto accedendo a una variabile di istanza @reciprocal tramite un attr_reader o un metodo di accesso semplice, o se sto chiamando un metodo che esegue un calcolo costoso. Il fatto che il nome del metodo sia un nome semplice, invece di dire calcReciprocal , suggerisce, ancora una volta, che la chiamata è almeno economica e probabilmente non ha effetti collaterali.
In Scala, la convenzione di denominazione è che i metodi con effetti collaterali prendono parentesi e metodi senza di essi, ma
val reciprocal = heading.reciprocal
potrebbe essere uno qualsiasi di:
// 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 = …
(Si noti che Scala consente varie cose che sono tuttavia scoraggiate dal style guide . Questo è uno dei miei maggiori fastidi con Scala.)
La mancanza di parentesi mi dice che la chiamata non ha effetti collaterali; il nome, ancora una volta, suggerisce che la chiamata dovrebbe essere relativamente economica. Oltre a ciò, non mi interessa come mi ottiene il valore.
In breve: conosci la lingua che stai utilizzando e scopri quali aspettative gli altri programmatori porteranno alla tua API. Tutto il resto è un dettaglio di implementazione.