La documentation ne mentionne que les types imbriqués, mais il n'est pas clair s'ils peuvent être utilisés comme espaces de noms. Je n'ai trouvé aucune mention explicite des espaces de noms.
La documentation ne mentionne que les types imbriqués, mais il n'est pas clair s'ils peuvent être utilisés comme espaces de noms. Je n'ai trouvé aucune mention explicite des espaces de noms.
Réponses:
Réponse de SevenTenEleven sur le forum des développeurs Apple :
Les espaces de noms ne sont pas par fichier; ils sont par cible (en fonction du paramètre de construction "Nom du module de produit"). Donc, vous vous retrouveriez avec quelque chose comme ça:
import FrameworkA import FrameworkB FrameworkA.foo()
Toutes les déclarations Swift sont considérées comme faisant partie d'un module, donc même lorsque vous dites "
NSLog
" (oui, cela existe toujours), vous obtenez ce que Swift considère comme "Foundation.NSLog
".
Aussi Chris Lattner tweeté à propos des espaces de noms .
L'espacement des noms est implicite dans Swift, toutes les classes (etc.) sont implicitement étendues par le module (cible Xcode) dans lequel elles se trouvent. Aucun préfixe de classe n'est nécessaire
Cela semble être très différent de ce que j'ai pensé.
forums.developer.apple.com
malheureusement pas importé ce fil dans le nouveau site de forums.
Je décrirais l'espace de noms de Swift comme ambitieux; il a reçu beaucoup de publicité qui ne correspond à aucune réalité significative sur le terrain.
Par exemple, les vidéos WWDC indiquent que si un framework que vous importez a une classe MyClass et que votre code a une classe MyClass, ces noms ne sont pas en conflit car "name mangling" leur donne des noms internes différents. En réalité, cependant, ils sont en conflit, dans le sens où MyClass de votre propre code l'emporte, et vous ne pouvez pas spécifier "Non non, je veux dire la MyClass dans le cadre" - dire TheFramework.MyClass
ne fonctionne pas (le compilateur sait ce que vous voulez dire , mais il dit qu'il ne peut pas trouver une telle classe dans le framework).
Mon expérience est que Swift n'est donc pas du tout espacé. En transformant l'une de mes applications d'Objective-C en Swift, j'ai créé un cadre intégré parce que c'était si facile et cool à faire. L'importation du framework, cependant, importe tous les éléments Swift dans le framework - alors hop, encore une fois, il n'y a qu'un seul espace de noms et c'est global. Et il n'y a pas d'en-tête Swift, vous ne pouvez donc cacher aucun nom.
EDIT: Dans seed 3, cette fonctionnalité commence maintenant à être mise en ligne, dans le sens suivant: si votre code principal contient MyClass et votre framework MyFramework contient MyClass, le premier éclipse le second par défaut, mais vous pouvez atteindre celui dans le framework en utilisant la syntaxe MyFramework.MyClass
. Ainsi, nous avons en fait les rudiments d'un espace de noms distinct!
EDIT 2: Dans la graine 4, nous avons maintenant des contrôles d'accès! De plus, dans l'une de mes applications, j'ai un cadre intégré et bien sûr, tout était caché par défaut et j'ai dû exposer explicitement tous les éléments de l'API publique. C'est une grande amélioration.
Foundation.NSArray
.
En faisant quelques expérimentations avec cela, j'ai fini par créer ces classes "namespaced" dans leurs propres fichiers en étendant le "package" racine. Je ne sais pas si cela va à l'encontre des meilleures pratiques ou si cela a des implications dont je suis conscient (?)
AppDelegate.swift
var n1 = PackageOne.Class(name: "Package 1 class")
var n2 = PackageTwo.Class(name: "Package 2 class")
println("Name 1: \(n1.name)")
println("Name 2: \(n2.name)")
PackageOne.swift
import Foundation
struct PackageOne {
}
PackageTwo.swift
import Foundation
struct PackageTwo {
}
PackageOneClass.swift
extension PackageOne {
class Class {
var name: String
init(name:String) {
self.name = name
}
}
}
PackageTwoClass.swift
extension PackageTwo {
class Class {
var name: String
init(name:String) {
self.name = name
}
}
}
Éditer:
Je viens de découvrir que la création de "sous-packages" dans le code ci-dessus ne fonctionnera pas si vous utilisez des fichiers séparés. Peut-être que quelqu'un peut dire pourquoi ce serait le cas?
Ajout des fichiers suivants à ce qui précède:
PackageOneSubPackage.swift
import Foundation
extension PackageOne {
struct SubPackage {
}
}
PackageOneSubPackageClass.swift
extension PackageOne.SubPackage {
class Class {
var name: String
init(name:String) {
self.name = name
}
}
}
Il lance une erreur de compilation: 'SubPackage' n'est pas un type de membre de 'PackageOne'
Si je déplace le code de PackageOneSubPackageClass.swift vers PackageOneSubPackage.swift, cela fonctionne. N'importe qui?
Modifier 2:
En jouant avec cela, j'ai découvert (dans Xcode 6.1 beta 2) qu'en définissant les packages dans un fichier, ils peuvent être étendus dans des fichiers séparés:
public struct Package {
public struct SubPackage {
public struct SubPackageOne {
}
public struct SubPackageTwo {
}
}
}
Voici mes fichiers dans un résumé: https://gist.github.com/mikajauhonen/d4b3e517122ad6a132b8
Je crois que cela est réalisé en utilisant:
struct Foo
{
class Bar
{
}
}
Ensuite, il peut être consulté en utilisant:
var dds = Foo.Bar();
enum
, pas struct
, vous ne pouvez pas instancier un Foo
.
Swift utilise des modules un peu comme en python (voir ici et ici ) et comme @Kevin Sylvestre l'a suggéré, vous pouvez également utiliser les types imbriqués comme espaces de noms.
Et pour prolonger la réponse de @Daniel A. White, à la WWDC, ils parlaient des modules dans Swift.
Est également expliqué ici :
Les types inférés rendent le code plus propre et moins sujet aux erreurs, tandis que les modules éliminent les en-têtes et fournissent des espaces de noms.
Les espaces de noms sont utiles lorsque vous devez définir une classe avec le même nom que la classe dans le cadre existant.
Supposons que votre application porte un
MyApp
nom et que vous deviez déclarer votre personnalisationUICollectionViewController
.
Vous n'avez pas besoin de préfixer et de sous-classe comme ceci:
class MAUICollectionViewController: UICollectionViewController {}
Fais-le comme ça:
class UICollectionViewController {} //no error "invalid redeclaration o..."
Pourquoi? . Parce que ce que vous avez déclaré est déclaré dans le module actuel , qui est votre cible actuelle . Et UICollectionViewController
from UIKit
est déclaré dans le UIKit
module.
Comment l'utiliser dans le module actuel?
var customController = UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
Comment les distinguer d'un autre module?
var customController = MyApp.UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
Vous pouvez utiliser extension
pour utiliser l' struct
approche s mentionnée pour l'espacement des noms sans avoir à indenter tout votre code vers la droite. Je suis jouer avec cela un peu et je ne suis pas sûr que je serais aller aussi loin que la création Controllers
et les Views
espaces de noms , comme dans l'exemple ci - dessous, mais il illustre bien jusqu'où il peut aller:
Profiles.swift :
// Define the namespaces
struct Profiles {
struct Views {}
struct ViewControllers {}
}
Profils / ViewControllers / Edit.swift
// Define your new class within its namespace
extension Profiles.ViewControllers {
class Edit: UIViewController {}
}
// Extend your new class to avoid the extra whitespace on the left
extension Profiles.ViewControllers.Edit {
override func viewDidLoad() {
// Do some stuff
}
}
Profils / Vues / Edit.swift
extension Profiles.Views {
class Edit: UIView {}
}
extension Profiles.Views.Edit {
override func drawRect(rect: CGRect) {
// Do some stuff
}
}
Je ne l'ai pas utilisé dans une application car je n'ai pas encore eu besoin de ce niveau de séparation, mais je pense que c'est une idée intéressante. Cela supprime le besoin de suffixes de classe même tels que le suffixe omniprésent * ViewController qui est extrêmement long.
Cependant, il ne raccourcit rien lorsqu'il est référencé comme dans des paramètres de méthode comme celui-ci:
class MyClass {
func doSomethingWith(viewController: Profiles.ViewControllers.Edit) {
// secret sauce
}
}
Au cas où quelqu'un serait curieux, à compter du 10 juin 2014, il s'agit d'un bug connu dans Swift:
de SevenTenEleven
" Bogue connu, désolé! Rdar: // problem / 17127940 La qualification des types Swift par leur nom de module ne fonctionne pas."