В документации упоминаются только вложенные типы, но не ясно, могут ли они использоваться в качестве пространств имен. Я не нашел явного упоминания о пространствах имен.
В документации упоминаются только вложенные типы, но не ясно, могут ли они использоваться в качестве пространств имен. Я не нашел явного упоминания о пространствах имен.
Ответы:
Ответ от SevenTenEleven на форуме разработчиков Apple :
Пространства имен не для каждого файла; они для каждой цели (в зависимости от настройки сборки «Product Module Name»). Таким образом, вы получите что-то вроде этого:
import FrameworkA import FrameworkB FrameworkA.foo()Все объявления Swift считаются частью некоторого модуля, поэтому даже когда вы говорите «
NSLog» (да, он все еще существует), вы получаете то, что Swift считает «Foundation.NSLog».
Также Крис Латтнер написал в Твиттере о пространстве имен .
Пространство имен неявно в Swift, все классы (и т. Д.) Неявно ограничены модулем (цель XCode), в котором они находятся. Префиксы классов не нужны
Кажется, что это совсем не то, о чем я думал.
forums.developer.apple.com, к сожалению, не импортировала эту ветку на новый форум.
Я бы назвал пространство имен Свифта желательным; было дано много рекламы, которая не соответствует какой-либо значимой реальности на местах.
Например, в видеороликах WWDC говорится, что если импортируемая среда имеет класс MyClass, а ваш код имеет класс MyClass, эти имена не конфликтуют, поскольку «искажение имен» дает им разные внутренние имена. В действительности, однако, они делают конфликт, в том смысле , что MyClass выигрывает свой собственный код, и вы не можете указать «Нет , нет, я имею в виду MyClass в рамках» - мол TheFramework.MyClassне работает (компилятор знает , что вы имеете в виду , но он говорит, что не может найти такой класс в рамках).
По моему опыту, Свифт, таким образом, не имеет ни малейшего пространства имен. Превратив одно из моих приложений из Objective-C в Swift, я создал встроенный фреймворк, потому что это было так легко и круто сделать. Однако при импорте фреймворка импортируются все элементы Swift в фреймворке - поэтому, прежде всего, снова существует только одно пространство имен, и оно глобально. И нет заголовков Swift, поэтому вы не можете скрыть имена.
РЕДАКТИРОВАТЬ: В начальном варианте 3 эта функция теперь начинает работать в сети, в следующем смысле: если ваш основной код содержит MyClass, а ваша инфраструктура MyFramework содержит MyClass, первый по умолчанию затмевает последний, но вы можете получить доступ к таковому в рамках используя синтаксис MyFramework.MyClass. Таким образом, у нас действительно есть зачатки отдельного пространства имен!
РЕДАКТИРОВАТЬ 2: В семени 4, у нас теперь есть контроль доступа! Кроме того, в одном из моих приложений у меня есть встроенная инфраструктура, и, конечно же, все было скрыто по умолчанию, и мне пришлось явным образом раскрыть все биты открытого API. Это большое улучшение.
Foundation.NSArray.
Проводя некоторые эксперименты с этим, я в итоге создал эти классы «пространства имен» в своих собственных файлах, расширив корневой «пакет». Не уверен, что это противоречит передовому опыту или имеет какие-либо последствия, о которых я не знаю (?)
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
}
}
}
Редактировать:
Просто обнаружил, что создание «подпакетов» в приведенном выше коде не будет работать, если использовать отдельные файлы. Может быть, кто-то может намекнуть, почему это так?
Добавляем следующие файлы к вышеуказанному:
PackageOneSubPackage.swift
import Foundation
extension PackageOne {
struct SubPackage {
}
}
PackageOneSubPackageClass.swift
extension PackageOne.SubPackage {
class Class {
var name: String
init(name:String) {
self.name = name
}
}
}
Выдает ошибку компилятора: SubPackage не является типом элемента PackageOne.
Если я перенесу код из PackageOneSubPackageClass.swift в PackageOneSubPackage.swift, он будет работать. Кто угодно?
Изменить 2:
Поигравшись с этим еще и выяснив (в Xcode 6.1 beta 2), что, определяя пакеты в одном файле, их можно расширять в отдельные файлы:
public struct Package {
public struct SubPackage {
public struct SubPackageOne {
}
public struct SubPackageTwo {
}
}
}
Вот мои файлы в гист: https://gist.github.com/mikajauhonen/d4b3e517122ad6a132b8
Я считаю, что это достигается с помощью:
struct Foo
{
class Bar
{
}
}
Тогда к нему можно получить доступ используя:
var dds = Foo.Bar();
enum, а не a struct, поэтому вы не можете создать экземпляр Foo.
Swift использует модули, очень похожие на python (см. Здесь и здесь ), и, как предложил @Kevin Sylvestre, вы также можете использовать вложенные типы в качестве пространств имен.
И чтобы расширить ответ от @Daniel A. White, в WWDC они быстро говорили о модулях.
Также здесь объясняется:
Предполагаемые типы делают код чище и менее подвержены ошибкам, в то время как модули устраняют заголовки и предоставляют пространства имен.
Пространства имен полезны, когда вам нужно определить класс с тем же именем, что и класс в существующей среде.
Предположим, у вашего приложения есть
MyAppимя, и вам нужно объявить свой кастомUICollectionViewController.
Вам не нужно префикс и подкласс, как это:
class MAUICollectionViewController: UICollectionViewController {}
Делай это так:
class UICollectionViewController {} //no error "invalid redeclaration o..."
Зачем? , Потому что то, что вы объявили, объявлено в текущем модуле , который является вашей текущей целью . И UICollectionViewControllerиз UIKitобъявлен в UIKitмодуле.
Как использовать его в текущем модуле?
var customController = UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
Как отличить их от другого модуля?
var customController = MyApp.UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
Вы можете extensionиспользовать упомянутый structподход к пространству имен без необходимости сдвигать весь ваш код вправо. Я играл с этим немного , и я не уверен , что я бы пойти так далеко , как создание Controllersи Viewsпространств имен , как в приведенном ниже примере, но он иллюстрирует , насколько далеко он может пойти:
Profiles.swift :
// Define the namespaces
struct Profiles {
struct Views {}
struct ViewControllers {}
}
Профили / 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
}
}
Профили / просмотров / Edit.swift
extension Profiles.Views {
class Edit: UIView {}
}
extension Profiles.Views.Edit {
override func drawRect(rect: CGRect) {
// Do some stuff
}
}
Я не использовал это в приложении, так как мне еще не нужен этот уровень разделения, но я думаю, что это интересная идея. Это устраняет необходимость в четных суффиксах классов, таких как вездесущий суффикс * ViewController, который раздражающе длинный.
Тем не менее, он ничего не сокращает, когда на него ссылаются, например, в параметрах метода, подобных этому:
class MyClass {
func doSomethingWith(viewController: Profiles.ViewControllers.Edit) {
// secret sauce
}
}
Если кому-то стало интересно, по состоянию на 10 июня 2014 года это известная ошибка в Swift:
От семидесятидесяти
«Известная ошибка, извините! Rdar: // problem / 17127940 Квалификация типов Swift по имени модуля не работает».