Funzioni rapide vs proprietà calcolate


26

Di 'che ho una lezione Eventcome segue:

class Event {
    private var attendees: [Person] = []

    // Case 1
    //*******
    // Should I use a func…
    func countOfAttendees() -> Int {
        return attendees.count
    }

    // …or a var
    var countOfAttendees: Int {
        return attendees.count
    }

    // Case 2
    //*******
    // Should I use a func…
    func countOfPaidAttendees() -> Int {
        return attendees.filter({$0.hasPaid}).count
    }

    // …or a var
    var countOfPaidAttendees: Int {
        return attendees.filter({$0.hasPaid}).count
    }
}

È consigliabile utilizzare funzioni o proprietà calcolate nei 2 casi indicati sopra?


2
stackoverflow.com/questions/24035276/… ... In breve: "Lascia che le tue funzioni siano funzioni e le tue proprietà siano proprietà".
Robert Harvey,

Risposte:


14

Seguire il principio di accesso uniforme ,

Tutti i servizi offerti da un modulo dovrebbero essere disponibili attraverso una notazione uniforme, che non tradisce se sono implementati attraverso l'archiviazione o il calcolo

Per me, questo significa che non scrivo funzioni che non accettano argomenti e restituiscono un valore. Uso sempre le proprietà calcolate. In questo modo, se in seguito decido di modificare la proprietà calcolata in una proprietà memorizzata, posso farlo senza avere l'impulso di rimuovere le parentesi ovunque nella mia app e senza avere un metodo "getter" separato che restituisce semplicemente il valore di una memoria proprietà, che sembra IMHO piuttosto dispendioso.

E se cambio una proprietà memorizzata in una proprietà calcolata, non devo aggiungere parentesi alla fine di essa e ovunque sia utilizzata nell'app.


Inizialmente ho scelto la risposta alla complessità di @ Anton, ma in pratica mi sono reso conto che è così che lo faccio ... proprietà di default.
Ashley Mills,

17

Direi che dipende dalla complessità del calcolo rispetto alla frequenza di utilizzo.

  • Se è O(1)/ *, usa la proprietà calcolata.
  • Se è O(N)+/ rare-use, utilizzare la funzione.
  • Se è O(N)+/ frequent-use, pensa se in futuro potresti decidere di utilizzare la memorizzazione nella cache o altre tecniche "intelligenti" per compensare la complessità, se "sì" allora usa la proprietà, se "no-no-no, è solo pesante" quindi usa la funzione .

2
Divertente come ho iniziato a farlo usando lo stesso ragionamento. Se "puoi" dargli l'impressione di essere una proprietà, anche se devi effettuare un'elaborazione leggera, purché non cambi l'oggetto, rendila una proprietà.
Dielson Sales,

9

Di recente ho iniziato a studiare Kotlin e hanno una grande euristica su quando usare le proprietà calcolate:

Funzioni vs Proprietà

In alcuni casi le funzioni senza argomenti potrebbero essere intercambiabili con proprietà di sola lettura. Sebbene la semantica sia simile, ci sono alcune convenzioni stilistiche su quando preferire l'una all'altra.

Preferisci una proprietà rispetto a una funzione quando l'algoritmo sottostante:

  • non getta
  • ha una complessità O (1)
  • è economico da calcolare (o individuato alla prima esecuzione)
  • restituisce lo stesso risultato su invocazioni

- https://kotlinlang.org/docs/reference/coding-conventions.html


Il "non gettare" è importante anche per Swift perché le proprietà non possono essere lanciate (ancora?)
alejandromp

"ha una complessità O (1)" è stato rimosso dalla documentazione
Mahmoud Shahoud,

7

In Swift, le funzioni senza parametri e le proprietà calcolate hanno quasi le stesse capacità (potrebbe esserci una differenza che una funzione senza parametro è anche una chiusura, mentre una proprietà calcolata non lo è).

La differenza è semanticamente. Se il tuo codice esegue un'azione e restituisce ad esempio una descrizione del risultato di tale azione, allora utilizzerei una funzione. Se il tuo codice calcola una proprietà ma dal punto di vista dell'utente questa potrebbe essere stata una proprietà memorizzata, o forse una proprietà memorizzata che richiede prima l'aggiornamento di un valore memorizzato nella cache, quindi utilizzerei una proprietà calcolata.

Una grande differenza: cosa succede se si chiama la funzione o la proprietà calcolata due volte? Per una proprietà calcolata mi aspetto che x = proprietà; y = property ha esattamente lo stesso comportamento di x = property; y = x tranne che potrebbe essere leggermente più lento. Per le funzioni, non sarei sorpreso se il comportamento fosse diverso.


4

Usa countOfAttendeese countOfPaidAttendees().


Una variabile calcolata è quella che restituisce un valore calcolato ogni volta che si accede. Cioè, non memorizza un valore. Internamente è implementato come una funzione.

Qual è la differenza con una funzione?

  • Semanticamente, una variabile è stato, una funzione è un'azione.
  • Una funzione regola l'accesso all'archivio privato. Una variabile calcolata può fare lo stesso in un modo più compatto. Esempio .
  • Una variabile calcolata può essere utilizzata con KVO, passata come #keypath e ha funzionalità per l'osservazione: willSet, didSet.

Dovresti usare una variabile quando

  • non getta
  • restituisce una proprietà semplice
  • non ha un effetto collaterale o un verbo nel suo nome
  • è O (1), cioè non comporta costi significativi. Nel tuo esempio sarà O (n).
  • è idempotente. Più invocazioni identiche restituiscono lo stesso valore o impostano l'oggetto sullo stesso stato.

Motivi irrilevanti per preferire una variabile a una funzione

  • Una variabile calcolata ti salva dalla digitazione (). Tuttavia, la chiarezza è più importante della brevità, quindi questo è un argomento debole.
  • Una variabile di sola lettura può essere sostituita come lettura / scrittura. Una funzione indica che è sempre di sola lettura. Tuttavia, Apple utilizza le proprietà per variabili di sola lettura come array.count. In caso di dubbi, cercare coerenza con la piattaforma.

risorse

Dal  WWDC 2014 - 204 Novità di Cocoa  > 24:40 Quando utilizzare una proprietà @

Usa la proprietà per tutto ciò che riguarda il valore o lo stato di un oggetto o la sua relazione con altri oggetti. Cattivi candidati:

  • Metodi che fanno le cose: caricare, analizzare, alternare, ... Hanno verbi nel suo nome.
  • Generatori: init, copia, enumerato,…. Questi metodi non sono idempotenti.
  • Metodi che cambiano stato: nextObject.

Da  Swift Style di Erica Sadun  > Proprietà calcolate e metodi

Una proprietà esprime una qualità intrinseca di un'istanza, mentre un metodo esegue un'azione.

  • I metodi hanno parametri; le proprietà no. Preferisci metodi per qualsiasi chiamata con effetti collaterali. Se un metodo fa qualcosa (ad esempio, carica, analizza, attiva o disattiva) o ha un nome verbo, non dovrebbe essere una proprietà.
  • Preferisci proprietà per valori semplici che puoi ottenere e / o impostare.
  • Le proprietà dovrebbero esprimere una qualità intrinseca semantica di un'istanza di tipo.
  • Le proprietà ti consentono di aggiungere osservatori tramite willSet e didSet. A differenza delle proprietà dell'istanza memorizzata, è necessario assegnare sempre un valore predefinito alle proprietà del tipo memorizzato.

Dalle  convenzioni di codifica di Kotlin> funzioni vs proprietà . Vedi la risposta di Daniel sopra .

Altre risorse senza informazioni pertinenti:


3

Userei un func. La programmazione orientata agli oggetti funziona perfettamente senza proprietà calcolate. Poiché stai recuperando un valore che è stato calcolato / filtrato, alcuni potrebbero obiettare che una proprietà calcolata sembra corretta. Ma ecco la mia lamentela, se lo fai allora la leggibilità ha un successo, perché sembra un valore.

In questo contesto non avrebbe senso provare ad assegnare il valore calcolato (e fortunatamente l'IDE ci aiuta a evitarlo) ma cosa succede se provo ad assegnare qualcosa che viene calcolato ma sembra un valore?

event.countOfAttendees = 0; // not possible

Durante l'utilizzo di func il chiamante sa che non hai a che fare direttamente con un valore:

event.countOfAttendees()

Penso che se si tratta di un oggetto comportamentale dovrebbe sembrare che si comporti piuttosto che sembrare una struttura di dati. Se il tuo oggetto è stupido e non ha alcun comportamento, allora perché provare a incapsularlo? In tal caso, potresti anche rendere pubblici i partecipanti

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.