Comment puis-je rendre l'initialiseur memberwise public, par défaut, pour les structures dans Swift?

165

J'ai un framework rapide qui définit une structure:

public struct CollectionTO {
    var index: Order
    var title: String
    var description: String
}

Cependant, je n'arrive pas à utiliser l'initialiseur implicite de membre sage d'un autre projet qui importe la bibliothèque. L'erreur est «CollectionTO» ne peut pas être initialisé car il n'a pas d'initialiseurs accessibles. c'est-à-dire qu'il ne donne pas à l'initialiseur implicite par défaut du membre sage le mot clé public.

var collection1 = CollectionTO(index: 1, title: "New Releases", description: "All the new releases")

Je dois ajouter ma propre méthode init comme ceci:

public struct CollectionTO {
    var index: Order
    var title: String
    var description: String

    public init(index: Order, title: String, description: String) {
        self.index = index;
        self.title = title;
        self.description = description;
    }

}

... mais je préférerais pas s'il y a une autre façon que quelqu'un sait?

bandejapaisa
la source

Réponses:

271

Citant le manuel:

"Initialiseur membre par défaut pour les types de structure L'initialiseur membre par défaut pour un type de structure est considéré comme privé si l'une des propriétés stockées de la structure est privée. Sinon, l'initialiseur a un niveau d'accès interne.

Comme pour l'initialiseur par défaut ci-dessus, si vous voulez qu'un type de structure publique soit initialisable avec un initialiseur membre lorsqu'il est utilisé dans un autre module, vous devez fournir vous-même un initialiseur membre public dans le cadre de la définition du type. "

Extrait de "Le langage de programmation Swift" , section "Contrôle d'accès" .

bandejapaisa
la source
289
Eh bien, c'est ennuyeux. :(
Dan Loewenherz
7
[ github.com/apple/swift-evolution/blob/master/proposals/… dit: «Citant Chris Lattner: Le comportement par défaut de l'initialiseur membre par défaut de Swift a au moins ces déficiences (IMO): 2) Contrôle d'accès + le membre initwise souvent vous oblige à le mettre en œuvre vous-même ». Alors peut-être est-ce juste une lacune qui existe sans raison en particulier. Impossible de trouver plus de références à ce sujet.
Jano
8
@DanLoewenherz Oui, ce n'est pas pratique. La justification est la suivante: «Un type public utilise par défaut des membres internes et non des membres publics. Si vous souhaitez qu'un membre de type soit public, vous devez le marquer explicitement comme tel. Cette exigence garantit que l'API publique d'un type est quelque chose que vous acceptez de publier et évite de présenter le fonctionnement interne d'un type comme une API publique par erreur. " Extrait de: Apple Inc. «The Swift Programming Language». iBooks. itun.es/gb/jEUH0.l
bandejapaisa
18
Une directive de compilateur serait bien de remplacer le comportement par défaut et de le rendre public.
bandejapaisa
9
Interne est un choix terrible pour un défaut, imo. Cela garantit essentiellement que vous rencontrerez des problèmes inattendus lors du référencement d'un module en externe pour la première fois. Pourquoi ne pas tout par défaut sur privé, afin que nous puissions savoir immédiatement quand quelque chose ne reçoit pas le niveau d'accès correct et ensuite décider s'il doit être public ou interne?
devios1
72

Bien qu'il ne soit pas possible d'avoir l'initialiseur membre par défaut au moins, vous pouvez en créer un rapidement en suivant les étapes suivantes:

  1. Faire de l'objet une classe temporairement au lieu d'une structure
  2. sauver
  3. Cliquez avec le bouton droit sur le nom de la classe et choisissez refactor -> Generate Memberwise Initializer
  4. Redéfinissez-le en struct
JP Aquino
la source
brillant.
Je ne saurais
1
Fonctionne et motive également à utiliser réellement des classes au lieu de structures youtube.com/watch?v=_V2sBURgUBI
Isaac Carol Weisberg
C'est un super conseil !!
Peymankh le
6
À partir de Xcode 11, vous pouvez également utiliser Generate Memberwise Initializer sur les structures!
Brock Batsell le
Fantastique!!! Ce n'est pas la bonne réponse, mais c'est un très bon conseil! M'a beaucoup aidé!
GuiOS
3

Jusqu'à ce qu'Apple change cela et le rende moins ennuyeux, vous pouvez utiliser https://github.com/Bouke/SwiftInitializerGenerator (ou tout autre) cette chose pour la création d'initialiseurs publics. Ce sera donc moins de travail. Je l'ai essayé et ça marche. Xcode version 10.0, High Sierra 10.13.6

Zaporozhchenko Oleksandr
la source
1

Nous avons maintenant une gemme ruby ​​💎 pour analyser un fichier de modèle de données rapide complet, ligne par ligne, et ajouter des modificateurs d'accès public, des initialiseurs par défaut publics pour les membres, et d'autres choses dans un fichier rapide de sortie généré automatiquement.

Ce joyau s'appelle swift_republic

Veuillez consulter la documentation suivante pour exécuter ce gem:

https://github.com/mehul90/swift_republic

Mehul Parmar
la source
1
Solution géniale !! J'ai déjà créé un wrapper pour swift_republicet fonctionne bien.
Md Shahed Hossain