2017-08-29 7 views
-2

Comment je peux utiliser l'initialisation paresseux avec get et set() de fermeture.Comment utiliser l'initialisation paresseuse avec la méthode getter/setter?

Voici le code d'initialisation paresseuse:

lazy var pi: Double = { 
     // Calculations... 
     return resultOfCalculation 
     }() 

et voici getter/code setter:

var pi: Double { 
    get { 
     //code to execute 
     return someValue 
    } 
    set(newValue) { 
     //code to execute 
    } 
} 
+0

pourquoi avez-vous besoin de cela? Y a-t-il une raison spécifique? – karthikeyan

+0

1. Ce ne sont pas des fermetures 2. Le getter ne fonctionnera pas tant qu'il n'aura pas été appelé. Qu'est-ce que vous essayez d'accomplir? –

+1

Comment anticipez-vous cela fonctionne? Avec une propriété paresseuse, elle est définie au premier accès. Avec un setter, il est réglé dès que le setter est utilisé. Voulez-vous un getter paresseux par défaut et un setter explicite? S'il vous plaît ajouter plus de détails. – ColGraff

Répondre

1

Je suppose que ce que vous essayez de faire est de générer paresseusement la valeur par défaut pour une propriété inscriptible . Je trouve souvent que les gens sautent à la paresse quand ce n'est pas nécessaire. Assurez-vous que cela vaut vraiment la peine. Cela ne vaudrait le coup que si la valeur par défaut est rarement utilisée, mais assez chère à créer. Mais si c'est votre situation, c'est une façon de le faire.

lazy implémente un motif très spécifique et assez limité qui n'est souvent pas ce que vous voulez. (Il n'est pas du tout certain que lazy était un ajout précieux au langage étant donné son fonctionnement, et il y a un travail actif pour le remplacer par un système d'attributs beaucoup plus puissant et utile.) Quand lazy n'est pas l'outil que vous voulez, vous venez de construire votre propre. Dans votre exemple, il ressemblerait à ceci:

private var _pi: Double? 
var pi: Double { 
    get { 
     if let pi = _pi { return pi } 
     let result = // calculations.... 
     _pi = result 
     return result 
    } 

    set { _pi = newValue } 
} 

Cela dit, dans la plupart des cas, je l'ai vu venir, il est préférable d'utiliser une valeur par défaut dans INIT:

func computePi() -> Double { 
    // compute and return value 
} 

// This is global. Globals are lazy (in a thread-safe way) automatically. 
let computedPi = computePi() 

struct X { 
    let pi: Double // I'm assuming it was var only because it might be overridden 
    init(pi: Double = computedPi) { 
     self.pi = pi 
    } 
} 

Le faire de cette façon calcule pi une seule fois dans le programme entier (plutôt qu'une fois par instance). Et il nous permet de faire pi "write-exactement-une fois" plutôt que l'état mutable. (Cela peut correspondre ou non à vos besoins, s'il faut vraiment écrire, alors var.)

Une approche similaire à la valeur par défaut peut être utilisée pour des objets coûteux à construire (plutôt que des objets statiques qui sont chers à calculer) sans avoir besoin d'un global.

struct X { 
    let pi: Double 
    init(pi: ExpensiveObject = ExpensiveObject()) { 
     self.pi = pi 
    } 
} 

Mais parfois, les getters et les setters conviennent mieux.

1

Le point d'une variable lazy est qu'il n'est pas initialisé jusqu'à ce qu'il soit récupéré, empêchant ainsi son initialiseur (éventuellement coûteux) de s'exécuter jusqu'à et à moins que la valeur de la variable soit accédée.

Eh bien, c'est exactement ce que fait un getter pour une variable calculée! Il ne court pas jusqu'à et à moins qu'il ne soit appelé. Par conséquent, un getter pour une variable calculée est paresseux.

La question, dans l'ensemble, est donc dénuée de sens. (La phrase "Comment je peux utiliser l'initialisation paresseux" révèle la faille, puisqu'une variable calculée est jamais initialisée - elle est calculée!)