A documentação menciona apenas tipos aninhados, mas não está claro se eles podem ser usados como espaços para nome. Não encontrei nenhuma menção explícita a namespaces.
A documentação menciona apenas tipos aninhados, mas não está claro se eles podem ser usados como espaços para nome. Não encontrei nenhuma menção explícita a namespaces.
Respostas:
Respondida por SevenTenEleven no fórum de desenvolvedores da Apple :
Os espaços para nome não são por arquivo; eles são por destino (com base na configuração de criação "Nome do módulo do produto"). Então você terminaria com algo assim:
import FrameworkA import FrameworkB FrameworkA.foo()
Todas as declarações do Swift são consideradas parte de algum módulo; portanto, mesmo quando você diz "
NSLog
" (sim, ele ainda existe), você está obtendo o que o Swift considera "Foundation.NSLog
".
Também Chris Lattner twittou sobre namespacing .
O espaço para nome está implícito no Swift, todas as classes (etc) têm o escopo implicitamente definido pelo módulo (destino do Xcode) em que estão. Nenhum prefixo de classe é necessário
Parece ser muito diferente do que venho pensando.
forums.developer.apple.com
, infelizmente , a Apple não importou esse segmento para o novo site de fóruns.
Eu descreveria o namespace de Swift como aspiracional; recebeu muita publicidade que não corresponde a nenhuma realidade significativa no terreno.
Por exemplo, os vídeos da WWDC afirmam que, se uma estrutura que você está importando tem uma classe MyClass e seu código tem uma classe MyClass, esses nomes não entram em conflito porque "mangling de nome" fornece nomes internos diferentes. Na realidade, no entanto, eles fazem conflito, no sentido de que vitórias MyClass seu próprio código, e você não pode especificar "Não, não, eu quero dizer a MyClass no quadro" - dizendo TheFramework.MyClass
não funciona (o compilador sabe o que quer dizer , mas diz que não consegue encontrar essa classe na estrutura).
Minha experiência é que Swift, portanto, não é um espaço de nome nem um pouco. Ao transformar um dos meus aplicativos do Objective-C para o Swift, criei uma estrutura incorporada porque era muito fácil e legal de fazer. A importação da estrutura, no entanto, importa todo o material Swift na estrutura - então, presto, mais uma vez, existe apenas um espaço para nome e é global. E não há cabeçalhos Swift, portanto você não pode ocultar nenhum nome.
EDIT: Na semente 3, esse recurso está começando a ficar online, no seguinte sentido: se seu código principal contiver MyClass e sua estrutura MyFramework contiver MyClass, a primeira ofusca a última por padrão, mas você pode alcançá-la na estrutura usando a sintaxe MyFramework.MyClass
. Assim, temos de fato os rudimentos de um espaço de nome distinto!
EDIT 2: Na semente 4, agora temos controles de acesso! Além disso, em um dos meus aplicativos eu tenho uma estrutura incorporada e, com certeza, tudo estava oculto por padrão e eu tive que expor explicitamente todos os bits da API pública. Esta é uma grande melhoria.
Foundation.NSArray
.
Ao fazer algumas experiências com isso, acabei criando essas classes "namespaced" em seus próprios arquivos, estendendo o "pacote" raiz. Não tenho certeza se isso é contra as melhores práticas ou se tem alguma implicação de que estou ciente (())
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:
Acabei de descobrir que a criação de "subpacotes" no código acima não funcionará se você estiver usando arquivos separados. Talvez alguém possa sugerir por que esse seria o caso?
Adicionando os seguintes arquivos ao acima:
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á lançando um erro de compilador: 'SubPackage' não é um tipo de membro de 'PackageOne'
Se eu mover o código de PackageOneSubPackageClass.swift para PackageOneSubPackage.swift, ele funcionará. Qualquer um?
Edição 2:
Brincando com isso ainda e descobri (no Xcode 6.1 beta 2) que, ao definir os pacotes em um arquivo, eles podem ser estendidos em arquivos separados:
public struct Package {
public struct SubPackage {
public struct SubPackageOne {
}
public struct SubPackageTwo {
}
}
}
Aqui estão meus arquivos em um sumário: https://gist.github.com/mikajauhonen/d4b3e517122ad6a132b8
Acredito que isso seja alcançado usando:
struct Foo
{
class Bar
{
}
}
Em seguida, ele pode ser acessado usando:
var dds = Foo.Bar();
enum
, não um struct
, portanto não poderá instanciar um Foo
.
O Swift usa módulos como o python (veja aqui e aqui ) e, como @Kevin Sylvestre sugeriu, você também pode usar os tipos aninhados como namespaces.
E para estender a resposta de Daniel A. White, na WWDC, eles estavam falando sobre os módulos rapidamente.
Também aqui é explicado:
Tipos inferidos tornam o código mais limpo e menos propenso a erros, enquanto os módulos eliminam cabeçalhos e fornecem espaços para nome.
Os espaços para nome são úteis quando você precisa definir a classe com o mesmo nome da classe na estrutura existente.
Suponha que seu aplicativo tenha
MyApp
nome e você precise declarar seu costumeUICollectionViewController
.
Você não precisa prefixar e subclassar como este:
class MAUICollectionViewController: UICollectionViewController {}
Faça isso deste modo:
class UICollectionViewController {} //no error "invalid redeclaration o..."
Por quê? . Porque o que você declarou está declarado no módulo atual , que é seu destino atual . E UICollectionViewController
de UIKit
é declarado no UIKit
módulo.
Como usá-lo no módulo atual?
var customController = UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
Como distingui-los de outro módulo?
var customController = MyApp.UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
Você pode usar extension
a struct
abordagem mencionada para espaçamento de nomes sem precisar recuar todo o seu código para a direita. Venho brincando um pouco com isso e não tenho certeza se iria criar espaços para nome Controllers
e Views
nomes, como no exemplo abaixo, mas ilustra o quão longe ele pode ir:
Profiles.swift :
// Define the namespaces
struct Profiles {
struct Views {}
struct ViewControllers {}
}
Perfis / 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
}
}
Perfis / Visualizações / Edit.swift
extension Profiles.Views {
class Edit: UIView {}
}
extension Profiles.Views.Edit {
override func drawRect(rect: CGRect) {
// Do some stuff
}
}
Não usei isso em um aplicativo, pois ainda não precisava desse nível de separação, mas acho que é uma ideia interessante. Isso elimina a necessidade de sufixos uniformes de classe, como o onipresente * ViewController, que é irritantemente longo.
No entanto, ele não reduz nada quando é referenciado, como em parâmetros de método como este:
class MyClass {
func doSomethingWith(viewController: Profiles.ViewControllers.Edit) {
// secret sauce
}
}
Caso alguém tenha curiosidade, em 10 de junho de 2014, este é um bug conhecido no Swift:
From SevenTenEleven
"Erro conhecido, desculpe! Rdar: // problem / 17127940 A qualificação de tipos Swift pelo nome do módulo não funciona."