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.