Как использовать пространства имен в Swift?


в документации упоминаются только вложенные типы, но неясно, могут ли они использоваться в качестве пространств имен. Я не нашел никакого явного упоминания о пространствах имен.

8   126   2014-06-03 00:35:14

8 ответов:

ответ Семнадцать семь на форум Apple dev:

пространства имен не для каждого файла; они для каждой цели (на основе Настройка сборки "имя модуля продукта"). Так что вы бы в конечном итоге с чем-то вот так:

import FrameworkA
import FrameworkB

FrameworkA.foo()

все объявления Swift считаются частью какой-либо модуль, так что даже когда вы говорите:"NSLog" (да, он все еще существует) вы получаете то, что Свифт думает как "Foundation.NSLog".

и Крис Lattner написал в твиттере о пространстве имен.

пространство имен неявно в Swift, все классы (etc) неявно область действия модуля (цель XCode), в котором они находятся. нет префиксов классов нужно

кажется, очень отличается то, что я думал.

Я бы описал пространство имен Swift как желательное; ему было дано много рекламы, которая не соответствует какой-либо значимой реальности на земле.

do конфликт, в том смысле, что ваш собственный код MyClass выигрывает, и вы не можете указать "Нет Нет, я имею в виду MyClass в рамках" - говорит TheFramework.MyClass не работает (компилятор знает, что вы имеете в виду, но он говорит, что не может найти такой класс в рамках).

мой опыт заключается в том, что Swift поэтому не имеет пространства имен ни в малейшей степени. Превратив одно из моих приложений из Objective-C в Swift, я создал встроенную структуру, потому что это было так легко и круто сделать. Импорт фреймворка, однако, импортирует все быстрые вещи в фреймворке-так престо, еще раз есть только одно пространство имен, и это глобально. И нет быстрых заголовков, поэтому вы не можете скрыть никаких имен.

EDIT: в seed 3 Эта функция теперь начинает работать в следующем смысле: если ваш основной код содержит MyClass, а ваш фреймворк MyFramework содержит MyClass, первый по умолчанию затмевает последний, но вы можете достичь его в фреймворке с помощью синтаксиса MyFramework.MyClass. Таким образом, мы действительно имеем зачатки отличное пространство имен!

EDIT 2: в seed 4, Теперь у нас есть контроль доступа! Кроме того, в одном из моих приложений у меня есть встроенный фреймворк и, конечно же, все было скрыто по умолчанию, и мне пришлось явно выставить все биты публичного API. Это большое улучшение.

при выполнении некоторых экспериментов с этим я закончил тем, что создал эти классы " namespaced "в своих собственных файлах, расширив корневой"пакет". Не уверен, что это противоречит лучшим практикам или если это имеет какие-либо последствия, я не знаю из(?)

AppDelegate.Свифт

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.Свифт

import Foundation

struct PackageOne {
}

PackageTwo.Свифт

import Foundation

struct PackageTwo {
}

PackageOneClass.Свифт

extension PackageOne {
    class Class {
        var name: String
        init(name:String) {
            self.name = name
        }
    }
}

PackageTwoClass.Свифт

extension PackageTwo {
    class Class {
        var name: String
        init(name:String) {
            self.name = name
        }
    }
}

Edit:

только что узнал, что создание "подпакетов" в приведенном выше коде не будет работать при использовании отдельных файлов. Может быть, кто-то может намекнуть на то, почему это было бы дело?

добавление следующих файлов выше:

PackageOneSubPackage.Свифт

import Foundation

extension PackageOne {
    struct SubPackage {
    }
}

PackageOneSubPackageClass.Свифт

extension PackageOne.SubPackage {
    class Class {
        var name: String
        init(name:String) {
            self.name = name
        }
    }
}

его бросает ошибка компилятора: 'SubPackage' не является членом типа 'PackageOne'

если я перемещаю код из PackageOneSubPackageClass.Свифт к Пакагеонесубпакаге.Свифт это работает. Кто?

Edit 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();

Swift использует модули так же, как в python (см. здесь и здесь) и как @ Kevin Sylvestre предложил вы также можете использовать вложенные типы как пространства имен.

и чтобы расширить ответ от @Daniel A. White, В WWDC они говорили о модулях в swift.

и здесь это объяснил:

выводимые типы делают код более чистым и менее подверженным ошибкам, в то время как модули исключают заголовки и предоставляют пространства имен.

Если кому-то любопытно, по состоянию на 10 июня 2014 года, это известная ошибка в Swift:

с Семнадцать семь

"известная ошибка, извините! rdar: / / problem / 17127940 квалификация типов Swift по имени их модуля не работает."

  • пространства имен полезны, когда вам нужно определить класс с помощью тот же имя как класс в существующей структуре.

  • предположим, что ваше приложение имеет 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 использовать указанный structs подход для пространства имен без необходимости отступа всего кода вправо. Я играл с этим немного, и я не уверен, что зашел бы так далеко, как создание Controllers и Views пространства имен, как в примере ниже, но это иллюстрирует, как далеко он может вперед:

профили.Свифт:

// Define the namespaces
struct Profiles {
  struct Views {}
  struct ViewControllers {}
}

Профили / ViewControllers / Edit.Свифт

// 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
  }
}

Профили/Вид/Редактирование.Свифт

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
  }
}