Funzioni rapide vs proprietà calcolate

21

Supponiamo di avere una classe Event come 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 le funzioni o proprietà calcolate nei 2 casi sopra indicati?

    
posta Ashley Mills 02.12.2015 - 11:58
fonte

6 risposte

13

Segui il principio di accesso uniforme ,

All services offered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation

Per me, questo significa che non scrivo le funzioni che non accettano argomenti e restituiscono un valore. Io uso sempre le proprietà calcolate. In questo modo, se in seguito decidessi di cambiare la proprietà calcolata in una proprietà memorizzata, potrei farlo senza avere la necessità di rimuovere i paren ovunque nella mia app e senza avere un metodo "getter" separato che restituisca solo il valore di una memoria proprietà, che sembra IMHO abbastanza sprecone.

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

    
risposta data 03.12.2015 - 01:17
fonte
13

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

  • Se è O(1) / * , quindi usa la proprietà calcolata.
  • Se è O(N)+ / rare-use , quindi usa la funzione.
  • Se è O(N)+ / frequent-use , pensa se in futuro potresti decidere di usare la cache o altre tecniche "intelligenti" per compensare la complessità, se "sì" allora usi proprietà, se "no-no- no, è solo pesante ", quindi usa la funzione.
risposta data 22.12.2015 - 22:51
fonte
7

In Swift, le funzioni senza parametri e proprietà calcolate hanno quasi le stesse funzionalità (potrebbe esserci 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 per esempio una descrizione del risultato di quell'azione, allora userei 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 alcuni valori memorizzati nella cache, quindi utilizzerei una proprietà calcolata.

Una grande differenza: cosa succede se chiami la funzione o la proprietà calcolata due volte? Per una proprietà calcolata mi aspetto che x = proprietà; y = proprietà ha esattamente lo stesso comportamento di x = proprietà; y = x tranne che potrebbe funzionare un po 'più lentamente. Per le funzioni, non sarei sorpreso se il comportamento fosse diverso.

    
risposta data 03.12.2015 - 10:02
fonte
6

Recentemente ho iniziato a imparare Kotlin e hanno una grande euristica su quando utilizzare le proprietà calcolate:

Functions vs Properties

In some cases functions with no arguments might be interchangeable with read-only properties. Although the semantics are similar, there are some stylistic conventions on when to prefer one to another.

Prefer a property over a function when the underlying algorithm:

  • does not throw
  • has a O(1) complexity
  • is cheap to calculate (or caсhed on the first run)
  • returns the same result over invocations

- link

    
risposta data 18.07.2016 - 14:48
fonte
3

Vorrei usare un func . La programmazione orientata agli oggetti funziona bene senza proprietà calcolate. Poiché si ottiene un valore che è stato calcolato / filtrato, alcuni potrebbero obiettare che una proprietà calcolata sembra giusta. Ma ecco la mia lamentela, se lo fai, allora la leggibilità prende un colpo, perché sembra un valore.

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

event.countOfAttendees = 0; // not possible

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

event.countOfAttendees()

Penso che se si tratta di un oggetto comportamentale dovrebbe apparire come se si comportasse 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

    
risposta data 02.12.2015 - 23:07
fonte
3

Utilizza countOfAttendees e countOfPaidAttendees() .

Una variabile calcolata è una variabile 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'archiviazione privata. Una variabile calcolata può fare lo stesso in un modo più compatto. Esempio .
  • Una variabile calcolata può essere utilizzata con KVO, passata come un #keypath e ha le funzionalità per osservare: willSet, didset.

Dovresti utilizzare 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 allo stesso stato.

Ragioni irrilevanti per preferire una variabile su 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 sovrascritta in 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 dubbio, cerca coerenza con la piattaforma.

Risorse

Da WWDC 2014 - 204 Novità di Coco > 24:40 Quando utilizzare una @property

Use property for anything that is about the value or state of an object or its relationship to other objects. Bad candidates:

  • Methods that do things: load, parse, toggle, …. They have verbs in its name.
  • Generators: init, copy, enumerated, …. These methods are not idempotent.
  • Methods which change state: nextObject.

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

A property expresses an inherent quality of an instance, while a method performs an action.

  • Methods have parameters; properties don’t. Prefer methods for any call with side effects. If a method does something (for example, it loads, parses, toggles, or prints) or has a verb name, it should not be a property.
  • Prefer properties for simple values that you can get and/or set.
  • Properties should express a semantic intrinsic quality of a type instance.
  • Properties allow you to add observers via willSet and didSet. Unlike stored instance properties, stored type properties must always be given a default value.

Da Convenzioni di codifica di Kotlin > funzioni vs proprietà . Vedi la risposta di Daniel sopra .

Altre risorse senza informazioni pertinenti:

risposta data 25.06.2018 - 14:03
fonte

Leggi altre domande sui tag