เอกสารอธิบายเฉพาะประเภทที่ซ้อนกัน แต่ไม่ชัดเจนว่าสามารถใช้เป็นเนมสเปซได้หรือไม่ ฉันไม่พบการกล่าวถึงเนมสเปซอย่างชัดเจน
เอกสารอธิบายเฉพาะประเภทที่ซ้อนกัน แต่ไม่ชัดเจนว่าสามารถใช้เป็นเนมสเปซได้หรือไม่ ฉันไม่พบการกล่าวถึงเนมสเปซอย่างชัดเจน
คำตอบ:
ตอบโดยSevenTenElevenในฟอรัม Apple dev :
เนมสเปซไม่ได้ต่อไฟล์; พวกเขาต่อเป้าหมาย (ขึ้นอยู่กับการตั้งค่าการสร้าง "ชื่อโมดูลผลิตภัณฑ์") ดังนั้นคุณจะจบลงด้วยสิ่งนี้:
import FrameworkA import FrameworkB FrameworkA.foo()
การประกาศของ Swift ทั้งหมดถือเป็นส่วนหนึ่งของโมดูลดังนั้นแม้ว่าคุณจะพูดว่า "
NSLog
" (ใช่ แต่ก็ยังมีอยู่) คุณจะได้รับสิ่งที่ Swift คิดว่าเป็น "Foundation.NSLog
"
นอกจากนี้คริสแลตต์เนอร์ได้เริ่มทวีตเกี่ยวกับ namespacing
การกำหนดเนมสเปซเป็นนัยใน Swift ทุกคลาส (ฯลฯ ) จะถูกกำหนดขอบเขตโดยโมดูล
ดูเหมือนจะแตกต่างอย่างมากกับสิ่งที่ฉันคิด
forums.developer.apple.com
ไซต์ใหม่ของฟอรัม
ฉันจะอธิบายการตั้งชื่อของสวิฟท์ว่าเป็นแรงบันดาลใจ มีการโฆษณามากมายที่ไม่สอดคล้องกับความเป็นจริงที่มีความหมาย
ตัวอย่างเช่นวิดีโอ WWDC ระบุว่าหากเฟรมเวิร์กที่คุณกำลังนำเข้ามีคลาส MyClass และรหัสของคุณมีคลาส MyClass ชื่อเหล่านั้นจะไม่ขัดแย้งกันเพราะ "ชื่อ mangling" ให้ชื่อภายในที่ต่างกัน ในความเป็นจริง แต่พวกเขาทำเช่นความขัดแย้งในแง่ที่ว่ารหัสของคุณเองชนะ MyClass และคุณไม่สามารถระบุ "ไม่มีไม่มีผมหมายถึง MyClass ในกรอบ" - บอกTheFramework.MyClass
ไม่ทำงาน (คอมไพเลอร์รู้ว่าสิ่งที่คุณหมายถึง แต่มันบอกว่าไม่พบคลาสดังกล่าวในกรอบงาน)
ประสบการณ์ของฉันคือ Swift ดังนั้นจึงไม่ได้ถูกตั้งชื่ออย่างน้อยที่สุด ในการเปลี่ยนหนึ่งในแอพของฉันจาก Objective-C เป็น Swift ฉันได้สร้างเฟรมเวิร์กที่ฝังตัวเพราะมันง่ายและยอดเยี่ยมในการทำ อย่างไรก็ตามการนำเข้าเฟรมเวิร์กนำเข้าข้อมูล Swift ทั้งหมดในเฟรมเวิร์กดังนั้น presto อีกครั้งมีเนมสเปซเพียงอันเดียวและเป็นส่วนกลาง และไม่มีส่วนหัว Swift ดังนั้นคุณจึงไม่สามารถซ่อนชื่อใด ๆ
แก้ไข:ใน seed 3 คุณลักษณะนี้กำลังเริ่มออนไลน์ในความหมายต่อไปนี้: หากรหัสหลักของคุณมี MyClass และกรอบงานของคุณ MyFramework มี MyClass ซึ่งเป็นอดีต overshadows หลังโดยค่าเริ่มต้น แต่คุณสามารถเข้าถึงหนึ่งในกรอบ MyFramework.MyClass
โดยใช้ไวยากรณ์ ในความเป็นจริงแล้วเรามีพื้นฐานของเนมสเปซที่แตกต่างกัน!
แก้ไข 2:ใน seed 4 ตอนนี้เรามีการควบคุมการเข้าถึง! นอกจากนี้ในหนึ่งในแอพของฉันฉันมีเฟรมเวิร์กที่ฝังอยู่และแน่นอนว่าทุกอย่างถูกซ่อนไว้โดยค่าเริ่มต้นและฉันต้องเปิดเผยบิตทั้งหมดของ API สาธารณะอย่างชัดเจน นี่คือการปรับปรุงครั้งใหญ่
Foundation.NSArray
ถ้าคุณมีอิทธิพลนั้นคุณยังสามารถเรียกมันว่า
ในขณะที่ทำการทดลองกับสิ่งนี้ฉันได้สร้างคลาส "namespaced" เหล่านี้ในไฟล์ของตนเองโดยขยายราก "แพ็คเกจ" ไม่แน่ใจว่าสิ่งนี้ขัดต่อแนวทางปฏิบัติที่ดีที่สุดหรือมีความหมายใด ๆ ที่ฉันทราบ (?)
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 เบต้า 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
ไม่ได้ดังนั้นคุณจึงไม่สามารถยกตัวอย่าง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
สำหรับ namespacing โดยไม่ต้องเยื้องรหัสทั้งหมดของคุณไปทางขวา ฉันเล่นกับสิ่งนี้เล็กน้อยและฉันไม่แน่ใจว่าฉันจะไปถึงการสร้าง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:
จากSevenTenEleven
"ข้อผิดพลาดที่รู้จักขออภัย! rdar: // problem / 17127940ประเภท Swift ที่ผ่านการรับรองโดยใช้ชื่อโมดูลไม่ทำงาน"