Dokumentasi hanya menyebutkan tipe bersarang, tetapi tidak jelas apakah mereka dapat digunakan sebagai ruang nama. Saya belum menemukan penyebutan ruang nama secara eksplisit.
Dokumentasi hanya menyebutkan tipe bersarang, tetapi tidak jelas apakah mereka dapat digunakan sebagai ruang nama. Saya belum menemukan penyebutan ruang nama secara eksplisit.
Jawaban:
Dijawab oleh SevenTenEleven di forum Apple dev :
Ruang nama bukan per file; mereka sesuai target (berdasarkan pengaturan bangunan "Nama Modul Produk"). Jadi Anda akan berakhir dengan sesuatu seperti ini:
import FrameworkA import FrameworkB FrameworkA.foo()
Semua deklarasi Swift dianggap sebagai bagian dari beberapa modul, jadi bahkan ketika Anda mengatakan "
NSLog
" (ya, itu masih ada) Anda mendapatkan apa yang Swift anggap sebagai "Foundation.NSLog
".
Juga Chris Lattner tweeted tentang namespacing .
Namespacing tersirat dalam Swift, semua kelas (dll) dicakup secara implisit oleh modul (target Xcode) tempat mereka berada. Tidak memerlukan awalan kelas
Tampaknya sangat berbeda dengan apa yang saya pikirkan.
forums.developer.apple.com
situs forum baru , sayangnya.
Saya akan menggambarkan ruang nama Swift sebagai aspirasional; telah diberikan banyak iklan yang tidak sesuai dengan kenyataan yang berarti di lapangan.
Misalnya, video WWDC menyatakan bahwa jika kerangka kerja yang Anda impor memiliki kelas MyClass dan kode Anda memiliki kelas MyClass, nama-nama itu tidak bertentangan karena "name mangling" memberi mereka nama internal yang berbeda. Pada kenyataannya, bagaimanapun, mereka lakukan konflik, dalam arti bahwa kode Anda sendiri menang MyClass, dan Anda tidak dapat menentukan "Tidak ada, maksud saya MyClass dalam rangka" - mengatakan TheFramework.MyClass
tidak bekerja (compiler tahu apa yang Anda maksud , tetapi dikatakan tidak dapat menemukan kelas seperti itu dalam framework).
Pengalaman saya adalah karena itu Swift tidak ditempatkan sedikitpun. Dalam mengubah salah satu aplikasi saya dari Objective-C ke Swift, saya membuat kerangka kerja yang tertanam karena sangat mudah dan keren untuk dilakukan. Mengimpor kerangka kerja, bagaimanapun, mengimpor semua hal Swift dalam kerangka kerja - begitu presto, sekali lagi hanya ada satu namespace dan global. Dan tidak ada header Swift sehingga Anda tidak dapat menyembunyikan nama.
EDIT: Di seed 3, fitur ini sekarang mulai online, dalam arti berikut: jika kode utama Anda berisi MyClass dan kerangka kerja Anda MyFramework berisi MyClass, yang pertama menaungi yang terakhir secara default, tetapi Anda dapat mencapai yang di dalam kerangka dengan menggunakan sintaks MyFramework.MyClass
. Jadi kita memang memiliki dasar-dasar namespace yang berbeda!
EDIT 2: Di seed 4, kami sekarang memiliki kontrol akses! Plus, di salah satu aplikasi saya, saya memiliki kerangka kerja tertanam dan tentu saja, semuanya disembunyikan secara default dan saya harus mengekspos semua bit API publik secara eksplisit. Ini adalah peningkatan besar.
Foundation.NSArray
.
Sambil melakukan beberapa eksperimen dengan ini saya akhirnya membuat kelas "namespaced" ini di file mereka sendiri dengan memperluas root "paket". Tidak yakin apakah ini bertentangan dengan praktik terbaik atau jika memiliki implikasi yang saya sadari (?)
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
}
}
}
Edit:
Baru tahu bahwa membuat "subpackages" dalam kode di atas tidak akan berfungsi jika menggunakan file terpisah. Mungkin seseorang bisa memberi petunjuk mengapa itu bisa terjadi?
Menambahkan file berikut ke yang di atas:
PackageOneSubPackage.swift
import Foundation
extension PackageOne {
struct SubPackage {
}
}
PackageOneSubPackageClass.swift
extension PackageOne.SubPackage {
class Class {
var name: String
init(name:String) {
self.name = name
}
}
}
Ini menimbulkan kesalahan kompiler: 'SubPackage' bukan tipe anggota 'PackageOne'
Jika saya memindahkan kode dari PackageOneSubPackageClass.swift ke PackageOneSubPackage.swift berfungsi. Siapa saja?
Edit 2:
Mengotak-atik ini dan menemukan (dalam Xcode 6.1 beta 2) bahwa dengan mendefinisikan paket dalam satu file, mereka dapat diperluas dalam file terpisah:
public struct Package {
public struct SubPackage {
public struct SubPackageOne {
}
public struct SubPackageTwo {
}
}
}
Berikut adalah file saya di intisari: https://gist.github.com/mikajauhonen/d4b3e517122ad6a132b8
Saya percaya ini dicapai dengan menggunakan:
struct Foo
{
class Bar
{
}
}
Kemudian dapat diakses menggunakan:
var dds = Foo.Bar();
enum
, bukan struct
, jadi Anda tidak dapat membuat instance a Foo
.
Swift menggunakan modul seperti di python (lihat di sini dan di sini ) dan seperti yang disarankan @Kevin Sylvestre, Anda juga dapat menggunakan tipe bersarang sebagai ruang nama.
Dan untuk memperluas jawaban dari @Daniel A. White, di WWDC mereka berbicara tentang modul dengan cepat.
Di sini juga dijelaskan:
Jenis yang disimpulkan membuat kode lebih bersih dan lebih rentan terhadap kesalahan, sementara modul menghilangkan tajuk dan memberikan ruang nama.
Namespaces berguna ketika Anda perlu mendefinisikan kelas dengan nama yang sama dengan kelas dalam kerangka kerja yang ada.
Misalkan aplikasi Anda memiliki
MyApp
nama, dan Anda harus mendeklarasikan kebiasaan AndaUICollectionViewController
.
Anda tidak perlu awalan dan subkelas seperti ini:
class MAUICollectionViewController: UICollectionViewController {}
Lakukan seperti ini:
class UICollectionViewController {} //no error "invalid redeclaration o..."
Mengapa? . Karena apa yang telah Anda deklarasikan dinyatakan dalam modul saat ini , yang merupakan target Anda saat ini . Dan UICollectionViewController
dari UIKit
dinyatakan dalam UIKit
modul.
Bagaimana cara menggunakannya dalam modul saat ini?
var customController = UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
Bagaimana membedakannya dari modul lain?
var customController = MyApp.UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
Anda dapat menggunakan extension
untuk menggunakan struct
pendekatan yang disebutkan untuk penempatan nama tanpa harus membuat indentasi semua kode Anda ke kanan. Saya sudah sedikit mempermainkan hal ini dan saya tidak yakin saya akan sejauh membuat Controllers
dan Views
namespaces seperti pada contoh di bawah ini, tapi itu menggambarkan seberapa jauh bisa:
Profiles : cepat:
// Define the namespaces
struct Profiles {
struct Views {}
struct ViewControllers {}
}
Profil / 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
}
}
Profil / Tampilan / Edit.swift
extension Profiles.Views {
class Edit: UIView {}
}
extension Profiles.Views.Edit {
override func drawRect(rect: CGRect) {
// Do some stuff
}
}
Saya belum pernah menggunakan ini di aplikasi karena saya belum membutuhkan tingkat pemisahan ini tetapi saya pikir ini ide yang menarik. Ini menghilangkan perlunya sufiks kelas genap seperti sufiks ViewController * yang ada di mana-mana yang sangat panjang.
Namun, itu tidak mempersingkat apa pun ketika direferensikan seperti dalam parameter metode seperti ini:
class MyClass {
func doSomethingWith(viewController: Profiles.ViewControllers.Edit) {
// secret sauce
}
}
Jika ada yang penasaran, pada 10 Juni 2014, ini adalah bug yang dikenal di Swift:
Dari SevenTenEleven
"Bug yang dikenal, maaf! Rdar: // masalah / 17127940 Jenis Swift Berkualifikasi dengan nama modul mereka tidak berfungsi."