La documentación solo menciona tipos anidados, pero no está claro si se pueden usar como espacios de nombres. No he encontrado ninguna mención explícita de espacios de nombres.
La documentación solo menciona tipos anidados, pero no está claro si se pueden usar como espacios de nombres. No he encontrado ninguna mención explícita de espacios de nombres.
Respuestas:
Respondido por SevenTenEleven en el foro de desarrollo de Apple :
Los espacios de nombres no son por archivo; son por objetivo (según la configuración de compilación "Nombre del módulo del producto"). Entonces terminarías con algo como esto:
import FrameworkA import FrameworkB FrameworkA.foo()
Todas las declaraciones de Swift se consideran parte de algún módulo, por lo que incluso cuando dice "
NSLog
" (sí, todavía existe), obtiene lo que Swift considera "Foundation.NSLog
".
También Chris Lattner tuiteó sobre el espacio de nombres .
El espacio de nombres está implícito en Swift, todas las clases (etc.) están implícitamente definidas por el módulo (destino de Xcode) en el que se encuentran. No se necesitan prefijos de clase
Parece ser muy diferente lo que he estado pensando.
forums.developer.apple.com
sitio de foros, desafortunadamente.
Describiría el espacio de nombres de Swift como aspiracional; Se le ha dado mucha publicidad que no corresponde a ninguna realidad significativa sobre el terreno.
Por ejemplo, los videos de WWDC establecen que si un marco que está importando tiene una clase MyClass y su código tiene una clase MyClass, esos nombres no entran en conflicto porque el "cambio de nombre" les da diferentes nombres internos. En realidad, sin embargo, sí entran en conflicto, en el sentido de que MyClass de su propio código gana, y no puede especificar "No, no, me refiero a MyClass en el marco": decir TheFramework.MyClass
que no funciona (el compilador sabe a qué se refiere , pero dice que no puede encontrar esa clase en el marco).
Mi experiencia es que Swift, por lo tanto, no tiene espacio de nombres en lo más mínimo. Al convertir una de mis aplicaciones de Objective-C a Swift, creé un marco incrustado porque era muy fácil y genial de hacer. Sin embargo, al importar el marco, se importan todas las cosas de Swift en el marco, por lo que, una vez más, solo hay un espacio de nombres y es global. Y no hay encabezados Swift, por lo que no puede ocultar ningún nombre.
EDITAR: en la semilla 3, esta característica ahora está comenzando a estar en línea, en el siguiente sentido: si su código principal contiene MyClass y su marco MyFramework contiene MyClass, el primero eclipsa al segundo de forma predeterminada, pero puede alcanzar el que está en el marco mediante el uso de la sintaxis MyFramework.MyClass
. ¡Así, de hecho, tenemos los rudimentos de un espacio de nombres distinto!
EDITAR 2: ¡ en la semilla 4, ahora tenemos controles de acceso! Además, en una de mis aplicaciones tengo un marco incrustado y, por supuesto, todo estaba oculto de forma predeterminada y tuve que exponer todos los bits de la API pública explícitamente. Esta es una gran mejora.
Foundation.NSArray
.
Mientras experimentaba un poco con esto, terminé creando estas clases de "espacios de nombres" en sus propios archivos extendiendo el "paquete" raíz. No estoy seguro de si esto va en contra de las mejores prácticas o si tiene alguna implicación que yo sepa (?)
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
}
}
}
Editar:
Me acabo de enterar de que crear "subpaquetes" en el código anterior no funcionará si se usan archivos separados. ¿Quizás alguien pueda insinuar por qué ese sería el caso?
Agregar los siguientes archivos a lo anterior:
PackageOneSubPackage.swift
import Foundation
extension PackageOne {
struct SubPackage {
}
}
PackageOneSubPackageClass.swift
extension PackageOne.SubPackage {
class Class {
var name: String
init(name:String) {
self.name = name
}
}
}
Está arrojando un error de compilación: 'SubPackage' no es un tipo de miembro de 'PackageOne'
Si muevo el código de PackageOneSubPackageClass.swift a PackageOneSubPackage.swift, funciona. ¿Nadie?
Edición 2:
Jugueteando con esto todavía y descubrí (en Xcode 6.1 beta 2) que al definir los paquetes en un archivo se pueden extender en archivos separados:
public struct Package {
public struct SubPackage {
public struct SubPackageOne {
}
public struct SubPackageTwo {
}
}
}
Aquí están mis archivos en un resumen: https://gist.github.com/mikajauhonen/d4b3e517122ad6a132b8
Creo que esto se logra usando:
struct Foo
{
class Bar
{
}
}
Entonces se puede acceder usando:
var dds = Foo.Bar();
enum
, no un struct
, por lo que no puede crear una instancia de a Foo
.
Swift usa módulos como Python (ver aquí y aquí ) y como @Kevin Sylvestre sugirió, también puede usar los tipos anidados como espacios de nombres.
Y para extender la respuesta de @Daniel A. White, en WWDC estaban hablando de los módulos rápidamente.
También aquí se explica:
Los tipos inferidos hacen que el código sea más limpio y menos propenso a errores, mientras que los módulos eliminan los encabezados y proporcionan espacios de nombres.
Los espacios de nombres son útiles cuando necesita definir una clase con el mismo nombre que la clase en el marco existente.
Supongamos que su aplicación tiene
MyApp
nombre y necesita declarar su costumbreUICollectionViewController
.
No necesita prefijos y subclases como este:
class MAUICollectionViewController: UICollectionViewController {}
Hazlo asi:
class UICollectionViewController {} //no error "invalid redeclaration o..."
¿Por qué? . Porque lo que has declarado se declara en el módulo actual , que es tu objetivo actual . Y UICollectionViewController
desde UIKit
se declara en UIKit
módulo.
¿Cómo usarlo dentro del módulo actual?
var customController = UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
¿Cómo distinguirlos de otro módulo?
var customController = MyApp.UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
Puede extension
usar el struct
enfoque de s mencionado para el espacio de nombres sin tener que sangrar todo su código hacia la derecha. He estado jugando con esto un poco y no estoy seguro que me gustaría ir tan lejos como la creación Controllers
y Views
espacios de nombres, como en el siguiente ejemplo, pero ilustra hasta qué punto puede ir:
Profiles.swift :
// Define the namespaces
struct Profiles {
struct Views {}
struct ViewControllers {}
}
Perfiles / 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
}
}
Perfiles / Vistas / Editar.swift
extension Profiles.Views {
class Edit: UIView {}
}
extension Profiles.Views.Edit {
override func drawRect(rect: CGRect) {
// Do some stuff
}
}
No he usado esto en una aplicación ya que aún no he necesitado este nivel de separación, pero creo que es una idea interesante. Esto elimina la necesidad de sufijos de clase pares, como el sufijo ubicuo * ViewController, que es molestamente largo.
Sin embargo, no acorta nada cuando se hace referencia, como en parámetros de métodos como este:
class MyClass {
func doSomethingWith(viewController: Profiles.ViewControllers.Edit) {
// secret sauce
}
}
En caso de que alguien tuviera curiosidad, a partir del 10 de junio de 2014, este es un error conocido en Swift:
De SevenTenEleven
"¡ Error conocido, lo siento! Rdar: // problem / 17127940 Los tipos de Swift que califican por su nombre de módulo no funcionan".