Est-ce que Swift a des modificateurs d’access?

Dans Objective-C, les données d’instance peuvent être public , protected ou private . Par exemple:

 @interface Foo : NSObject { @public int x; @protected: int y; @private: int z; } -(int) apple; -(int) pear; -(int) banana; @end 

Je n’ai trouvé aucune mention de modificateurs d’access dans la référence Swift. Est-il possible de limiter la visibilité des données dans Swift?

À partir de Swift 3.0.1 , il y a 4 niveaux d’access , décrits ci-dessous, du plus élevé (le moins ressortingctif) au plus faible (le plus ressortingctif).


1. open et public

Activer une entité à utiliser en dehors du module de définition (cible). Vous utilisez généralement public access open ou public pour spécifier l’interface publique à une structure.

Toutefois, open access open s’applique uniquement aux classes et aux membres de classe , et diffère de public access public comme suit:

  • public classes public et les membres de classe ne peuvent être sous-classés et remplacés que dans le module de définition (cible).
  • open classes open et les membres de classe peuvent être sous-classés et remplacés à la fois à l’intérieur et à l’extérieur du module de définition (cible).
 // First.framework – A.swift open class A {} 

 // First.framework – B.swift public class B: A {} // ok 

 // Second.framework – C.swift import First internal class C: A {} // ok 

 // Second.framework – D.swift import First internal class D: B {} // error: B cannot be subclassed 

2. internal

Permet à une entité d’être utilisée dans le module de définition (cible). Vous utilisez généralement internal access internal lors de la définition de la structure interne d’une application ou d’un framework.

 // First.framework – A.swift internal struct A {} 

 // First.framework – B.swift A() // ok 

 // Second.framework – C.swift import First A() // error: A is unavailable 

3. fileprivate

Limite l’utilisation d’une entité à son fichier source définissant. En fileprivate générale, vous utilisez l’access par fileprivate pour masquer les détails d’implémentation d’une fonctionnalité spécifique lorsque ces informations sont utilisées dans un fichier entier.

 // First.framework – A.swift internal struct A { fileprivate static let x: Int } Ax // ok 

 // First.framework – B.swift Ax // error: x is not available 

4. private

Limite l’utilisation d’une entité à sa déclaration englobante. Vous utilisez généralement private access private pour masquer les détails d’implémentation d’une fonctionnalité spécifique lorsque ces informations ne sont utilisées que dans une seule déclaration.

 // First.framework – A.swift internal struct A { private static let x: Int internal static func doSomethingWithX() { x // ok } } Ax // error: x is unavailable 

Quand on parle de faire une “méthode privée” dans Swift ou ObjC (ou ruby ​​ou java ou…), ces méthodes ne sont pas vraiment privées. Il n’y a pas de contrôle d’access réel autour d’eux. Tout langage offrant une petite introspection permet aux développeurs d’accéder aux valeurs extérieures à la classe s’ils le souhaitent.

Donc, ce dont nous parlons en réalité, c’est une façon de définir une interface publique qui présente simplement la fonctionnalité que nous voulons, et «cache» le rest que nous considérons comme «privé».

Le mécanisme Swift pour la déclaration des interfaces est le protocol , et il peut être utilisé à cette fin.

 protocol MyClass { var publicProperty:Int {get set} func publicMethod(foo:Ssortingng)->Ssortingng } class MyClassImplementation : MyClass { var publicProperty:Int = 5 var privateProperty:Int = 8 func publicMethod(foo:Ssortingng)->Ssortingng{ return privateMethod(foo) } func privateMethod(foo:Ssortingng)->Ssortingng{ return "Hello \(foo)" } } 

Rappelez-vous que les protocoles sont des types de première classe et peuvent être utilisés partout où un type peut. Et , lorsqu’ils sont utilisés de cette manière, ils exposent uniquement leurs propres interfaces, pas celles du type d’implémentation.

Ainsi, tant que vous utilisez MyClass au lieu de MyClassImplementation dans vos types de parameters, etc., tout devrait fonctionner:

 func breakingAndEntering(foo:MyClass)->Ssortingng{ return foo.privateMethod() //ERROR: 'MyClass' does not have a member named 'privateMethod' } 

Il y a des cas d’affectation directe où vous devez être explicite avec type au lieu de compter sur Swift pour l’inférer, mais cela ne semble pas être un facteur décisif:

 var myClass:MyClass = MyClassImplementation() 

Utiliser les protocoles de cette façon est sémantique, raisonnablement concis, et à mes yeux ressemble beaucoup aux extensions de classe que nous avons utilisées à cette fin dans ObjC.

Autant que je sache, il n’y a pas de mots clés “public”, “private” ou “protected”. Cela suggère que tout est public.

Cependant, Apple s’attend à ce que les utilisateurs utilisent des « protocoles » (appelés interfaces par le rest du monde) et le modèle de conception d’usine pour masquer les détails du type d’implémentation.

C’est souvent un bon modèle de conception à utiliser de toute façon; comme il vous permet de modifier votre hiérarchie de classes d’ implémentation , tout en conservant le même type de système logique .

En utilisant une combinaison de protocoles, de fermetures et de classes nestedes / internes, il est possible d’utiliser quelque chose du type du module pour masquer des informations dans Swift dès maintenant. Ce n’est pas super propre ou agréable à lire mais ça marche.

Exemple:

 protocol HuhThing { var huh: Int { get set } } func HuhMaker() -> HuhThing { class InnerHuh: HuhThing { var innerVal: Int = 0 var huh: Int { get { return mysteriousMath(innerVal) } set { innerVal = newValue / 2 } } func mysteriousMath(number: Int) -> Int { return number * 3 + 2 } } return InnerHuh() } HuhMaker() var h = HuhMaker() h.huh // 2 h.huh = 32 h.huh // 50 h.huh = 39 h.huh // 59 

innerVal et mysteriousMath sont cachés ici de l’extérieur et toute tentative de se frayer un chemin dans l’object devrait entraîner une erreur.

Je ne suis qu’une partie de ma lecture des documents Swift, donc s’il y a une faille ici, merci de le signaler, j’aimerais savoir.

Swift 4

Comme indiqué dans la documentation de Swift – Contrôle d’access , Swift 4 dispose de 5 contrôles d’access :

  • open et public : accessible depuis les entités de leur module et toutes les entités du module qui importent le module de définition.

  • internal : accessible uniquement à partir des entités de leur module. C’est le niveau d’access par défaut.

  • fileprivate et private : on ne peut y accéder que de manière limitée dans une scope limitée où vous les définissez.


Quelle est la différence entre ouvert et public ?

open est le même que public dans les versions précédentes de Swift, ils permettent aux classes d’autres modules de les utiliser et de les hériter, c’est-à-dire qu’ils peuvent être sous-classés par rapport aux autres modules. En outre, ils permettent aux membres d’autres modules de les utiliser et de les remplacer. La même logique vaut pour leurs modules.

public permet aux classes d’un autre module de les utiliser, mais pas de les hériter, c’est-à-dire qu’elles ne peuvent pas être sous-classées par rapport aux autres modules. En outre, ils permettent aux membres d’autres modules de les utiliser, mais PAS de les remplacer. Pour leurs modules, ils ont la même logique ouverte (ils permettent aux classes de les utiliser et de les hériter; elles permettent aux membres de les utiliser et de les remplacer).

Quelle est la différence entre fileprivate et private ?

fileprivate est accessible depuis la totalité de leurs fichiers.

Vous ne pouvez accéder à private qu’à partir de leur déclaration unique et aux extensions de cette déclaration qui se trouvent dans le même fichier; Par exemple:

 // Declaring "A" class that has the two types of "private" and "fileprivate": class A { private var aPrivate: Ssortingng? fileprivate var aFileprivate: Ssortingng? func accessMySelf() { // this works fine self.aPrivate = "" self.aFileprivate = "" } } // Declaring "B" for checking the abiltiy of accessing "A" class: class B { func accessA() { // create an instance of "A" class let aObject = A() // Error! this is NOT accessable... aObject.aPrivate = "I CANNOT set a value for it!" // this works fine aObject.aFileprivate = "I CAN set a value for it!" } } 

Quelles sont les différences entre Swift 3 et Swift 4 Access Control?

Comme mentionné dans la proposition SE-0169 , la seule amélioration apscope à Swift 4 est que la scope du contrôle d’access privé a été étendue pour être accessible à partir d’ extensions de cette déclaration dans le même fichier; Par exemple:

 struct MyStruct { private let myMessage = "Hello World" } extension MyStruct { func printMyMessage() { print(myMessage) // In Swift 3, you will get a comstack time error: // error: 'myMessage' is inaccessible due to 'private' protection level // In Swift 4 it should works fine! } } 

Il n’est donc pas nécessaire de déclarer myMessage comme fichier privé pour être accessible dans tout le fichier.

Remarque: Si vous avez rencontré des problèmes liés à la non-compilation de Swift 4 avec un ancien projet Swift 3 migré , vous pouvez vérifier cette Q & R.

A partir de Xcode 6 beta 4, Swift dispose de modificateurs d’access. A partir des notes de publication:

Le contrôle d’access rapide a trois niveaux d’access:

  • les entités privées ne sont accessibles que depuis le fichier source où elles sont définies.
  • Les entités internes sont accessibles partout dans la cible où elles sont définies.
  • Les entités publiques sont accessibles depuis n’importe où dans la cible et depuis tout autre contexte qui importe le module de la cible actuelle.

La valeur implicite par défaut est internal . Par conséquent, dans une cible d’application, vous pouvez désactiver les modificateurs d’access, sauf lorsque vous souhaitez être plus ressortingctif. Dans une cible d’infrastructure (par exemple, si vous intégrez une infrastructure pour partager du code entre une application et une extension de partage ou une vue Aujourd’hui), utilisez public pour désigner l’API que vous souhaitez exposer aux clients de votre infrastructure.

Swift 3.0 fournit cinq contrôles d’access différents:

  1. ouvrir
  2. Publique
  3. interne
  4. fichierprivate
  5. privé

L’ access ouvert et l’ access public permettent aux entités d’être utilisées dans n’importe quel fichier source à partir de leur module de définition, ainsi que dans un fichier source provenant d’un autre module qui importe le module de définition. Vous utilisez généralement un access ouvert ou public pour spécifier l’interface publique à une structure.

L’ access interne permet aux entités d’être utilisées dans n’importe quel fichier source à partir de leur module de définition, mais pas dans un fichier source en dehors de ce module. Vous utilisez généralement un access interne lors de la définition de la structure interne d’une application ou d’un framework.

L’ access à un fichier privé restreint l’utilisation d’une entité à son propre fichier source définissant. Utilisez l’access privé sur fichier pour masquer les détails d’implémentation d’une fonctionnalité spécifique lorsque ces détails sont utilisés dans un fichier entier.

L’ access privé limite l’utilisation d’une entité à la déclaration finale. Utilisez un access privé pour masquer les détails d’implémentation d’une fonctionnalité spécifique lorsque ces informations ne sont utilisées que dans une seule déclaration.

Le libre access est le niveau d’access le plus élevé (le moins ressortingctif) et l’ access privé est le niveau d’access le plus bas (le plus ressortingctif).

Niveaux d’access par défaut

Toutes les entités de votre code (avec quelques exceptions spécifiques) ont un niveau d’access interne par défaut si vous ne spécifiez pas vous-même de niveau d’access explicite. Par conséquent, dans de nombreux cas, vous n’avez pas besoin de spécifier un niveau d’access explicite dans votre code.

La note de publication sur le sujet:

Les classes déclarées comme publiques ne peuvent plus être sous-classées en dehors de leur module de définition, et les méthodes déclarées comme publiques ne peuvent plus être remplacées en dehors de leur module de définition. Pour autoriser une classe à être sous-classée en externe ou une méthode à remplacer en externe, déclarez-les comme ouvertes, ce qui correspond à un nouveau niveau d’access public. Les classes et méthodes Objective-C imscopes sont désormais toutes imscopes comme ouvertes plutôt que publiques. Les tests unitaires qui importent un module à l’aide d’une importation @testable seront toujours autorisés à sous-classer les classes publiques ou internes, ainsi qu’à remplacer les méthodes publiques ou internes. (SE-0117)

Plus d’informations et de détails: Le langage de programmation rapide (contrôle d’access)

Non, ce n’est pas possible. Il n’y a pas de méthodes et de variables privées / protégées.

Tout est public.

Dans la version bêta 6, la documentation indique qu’il existe trois modificateurs d’access différents:

  • Publique
  • Interne
  • Privé

Et ces trois s’appliquent aux classes, protocoles, fonctions et propriétés.

 public var somePublicVariable = 0 internal let someInternalConstant = 0 private func somePrivateFunction() {} 

Pour plus d’informations, consultez Contrôle d’access .

Mécanismes de contrôle d’access introduits dans Xcode 6 :

Swift propose trois niveaux d’access différents pour les entités de votre code. Ces niveaux d’access sont relatifs au fichier source dans lequel une entité est définie et également au module auquel appartient le fichier source.

  • L’access public permet aux entités d’être utilisées dans n’importe quel fichier source à partir de leur module de définition, ainsi que dans un fichier source provenant d’un autre module qui importe le module de définition. Vous utilisez généralement l’access public lorsque vous spécifiez l’interface publique à une structure.
  • L’access interne permet aux entités d’être utilisées dans n’importe quel fichier source à partir de leur module de définition, mais pas dans un fichier source en dehors de ce module. Vous utilisez généralement un access interne lors de la définition de la structure interne d’une application ou d’un framework.
  • L’access privé limite l’utilisation d’une entité à son propre fichier source définissant. Utilisez un access privé pour masquer les détails d’implémentation d’une fonctionnalité spécifique.

L’access public est le niveau d’access le plus élevé (le moins ressortingctif) et l’access privé est le niveau d’access le plus bas (ou le plus ressortingctif).

L’access par défaut est interne , et n’a donc pas besoin d’être spécifié. Notez également que le spécificateur privé ne fonctionne pas au niveau de la classe, mais au niveau du fichier source. Cela signifie que pour obtenir des parties d’une classe vraiment privé, vous devez séparer dans un fichier qui lui est propre. Cela introduit également des cas intéressants en ce qui concerne les tests unitaires …

Un autre point que j’ai fait remarquer, qui est commenté dans le lien ci-dessus, est que vous ne pouvez pas «mettre à niveau» le niveau d’access. Si vous sous-classe quelque chose, vous pouvez le restreindre davantage, mais pas l’inverse.

Ce dernier bit affecte également les fonctions, les n-uplets et sûrement d’autres éléments, si une fonction utilise une classe privée , la fonction interne ou publique n’est pas valide, car ils peuvent ne pas avoir access à la classe privée . Cela se traduit par un avertissement du compilateur et vous devez redéclarer la fonction en tant que fonction privée .

Une des options que vous pouvez utiliser est d’emballer la création de l’instance dans une fonction et de fournir les getters et setters appropriés dans un constructeur:

 class Counter { let inc: () -> Int let dec: () -> Int init(start: Int) { var n = start inc = { ++n } dec = { --n } } } let c = Counter(start: 10) c.inc() // 11 c.inc() // 12 c.dec() // 11 

Maintenant, en bêta 4, ils ont ajouté des modificateurs d’access à Swift.

à partir de notes Xcode 6 beta 4 realese :

Le contrôle d’access rapide a trois niveaux d’access:

  • private entités private ne sont accessibles que depuis le fichier source où elles sont définies.
  • internal entités internal sont accessibles partout dans la cible où elles sont définies.
  • public entités public sont accessibles depuis n’importe où dans la cible et depuis tout autre contexte qui importe le module de la cible actuelle.

Par défaut, la plupart des entités d’un fichier source ont un access interne. Cela permet aux développeurs d’applications d’ignorer largement le contrôle d’access tout en autorisant les développeurs de framework à contrôler totalement l’API du framework.

La grammaire du langage ne comporte pas les mots clés «public», «private» ou «protected». Cela suggère que tout est public. Bien sûr, il pourrait y avoir une autre méthode pour spécifier des modificateurs d’access sans ces mots-clés, mais je n’ai pas pu la trouver dans la référence de langue.

Swift 3 et 4 ont également apporté beaucoup de changements aux niveaux d’access aux variables et aux méthodes. Swift 3 et 4 ont maintenant 4 niveaux d’access différents, où l’ access ouvert / public est le niveau d’access le plus élevé (le moins ressortingctif) et l’ access privé est le niveau d’access le plus bas (le plus ressortingctif):

  • les fonctions privées et les membres ne sont accessibles que dans le cadre de l’entité elle-même (struct, class,…) et ses extensions (dans Swift 3, les extensions étaient également restreintes)
  • Les fonctions fileprivate et les membres ne sont accessibles que depuis le fichier source où ils sont déclarés.
  • les fonctions internes et les membres (qui est la valeur par défaut, si vous n’ajoutez pas explicitement un mot-clé de niveau d’access) sont accessibles partout dans la cible où ils sont définis. C’est pourquoi TestTarget n’a pas automatiquement access à toutes les sources, elles doivent être marquées comme accessibles dans l’inspecteur de fichiers de xCode.
  • Les fonctions et les membres ouverts ou publics sont accessibles de n’importe où dans la cible et à partir de tout autre contexte qui importe le module de la cible actuelle.

Intéressant:

Au lieu de marquer chaque méthode ou membre comme étant “privé”, vous pouvez couvrir certaines méthodes (par exemple, les fonctions d’aide généralement) dans une extension d’une classe / struct et marquer l’extension entière comme “privée”.

 class foo { } private extension foo { func somePrivateHelperFunction01() { } func somePrivateHelperFunction02() { } func somePrivateHelperFunction03() { } } 

Cela peut être une bonne idée pour obtenir un meilleur code maintenable. Et vous pouvez facilement basculer (par exemple pour les tests unitaires) sur non-privé en changeant simplement un mot.

Documentation Apple

Espérons que cela permettra de gagner du temps pour ceux qui veulent quelque chose qui s’apparente à des méthodes protégées:

Selon d’autres réponses, swift fournit désormais le modificateur ‘private’ – qui est défini en fonction du fichier plutôt que de la classe, par exemple en Java ou en C #. Cela signifie que si vous voulez des méthodes protégées, vous pouvez le faire avec des méthodes privées rapides si elles sont dans le même fichier

  1. Créer une classe de base pour contenir des méthodes “protégées” (en réalité privées)
  2. Sous-classe de cette classe pour utiliser les mêmes méthodes
  3. Dans d’autres fichiers, vous ne pouvez pas accéder aux méthodes de la classe de base, même lorsque vous sous-classe soit

p.ex. Fichier 1:

 class BaseClass { private func protectedMethod() { } } class SubClass : BaseClass { func publicMethod() { self.protectedMethod() //this is ok as they are in same file } } 

Fichier 2:

 func test() { var a = BaseClass() a.protectedMethod() //ERROR var b = SubClass() b.protectedMethod() //ERROR } class SubClass2 : BaseClass { func publicMethod() { self.protectedMethod() //ERROR } 

}

jusqu’à ce que swift 2.0 il y avait seulement trois niveaux d’access [Public, interne, privé] mais dans swift 3.0, apple a ajouté deux nouveaux niveaux d’access qui sont [Open, fileType], donc swift 3.0 il y a 5 niveaux d’access de ces deux niveaux d’access 1. Ouvert: c’est très similaire à Public mais la seule différence est que le Public peut accéder à la sous-classe et à la substitution, et Open access level ne peut accéder à cette image. entre access ouvert et public

Maintenant au deuxième nouveau niveau d’access 2. le type de fichier est une version plus grande du niveau d’access privé ou inférieur à interne Le type de fichier peut accéder à la partie étendue de [class, struct, enum] et privé ne peut pas accéder à la partie étendue du code la scope lexicale cette image est prise à partir du site Web Medium et cela décrit la différence entre fileType et niveau d’access privé