Tài liệu này chỉ đề cập đến các kiểu lồng nhau, nhưng không rõ liệu chúng có thể được sử dụng làm không gian tên hay không. Tôi không tìm thấy bất kỳ đề cập rõ ràng về không gian tên.
Tài liệu này chỉ đề cập đến các kiểu lồng nhau, nhưng không rõ liệu chúng có thể được sử dụng làm không gian tên hay không. Tôi không tìm thấy bất kỳ đề cập rõ ràng về không gian tên.
Câu trả lời:
Đã được trả lời bởi SevenTenEleven trong diễn đàn nhà phát triển của Apple :
Không gian tên không phải là mỗi tệp; chúng theo từng mục tiêu (dựa trên cài đặt xây dựng "Tên mô-đun sản phẩm"). Vì vậy, bạn sẽ kết thúc với một cái gì đó như thế này:
import FrameworkA import FrameworkB FrameworkA.foo()
Tất cả các khai báo Swift được coi là một phần của một số mô-đun, vì vậy ngay cả khi bạn nói "
NSLog
" (vâng, nó vẫn tồn tại) bạn sẽ nhận được những gì Swift nghĩ là "Foundation.NSLog
".
Ngoài ra Chris Lattner đã tweet về không gian tên .
Không gian tên được ẩn trong Swift, tất cả các lớp (v.v.) được ẩn trong phạm vi bởi mô-đun (mục tiêu Xcode) mà chúng đang ở. Không cần tiền tố lớp
Có vẻ rất khác những gì tôi đã nghĩ.
forums.developer.apple.com
thật không may , Apple đã không nhập chủ đề đó vào trang diễn đàn mới .
Tôi sẽ mô tả không gian tên của Swift là khát vọng; nó đã được cung cấp rất nhiều quảng cáo không tương ứng với bất kỳ thực tế có ý nghĩa nào.
Ví dụ: các video WWDC nói rằng nếu một khung bạn đang nhập có một lớp MyClass và mã của bạn có một lớp MyClass, các tên đó không xung đột vì "xáo trộn tên" cung cấp cho chúng các tên nội bộ khác nhau. Trên thực tế, tuy nhiên, họ làm xung đột, theo nghĩa là chiến thắng MyClass mã riêng của bạn, và bạn không thể xác định "Không không, tôi có nghĩa là MyClass trong khuôn khổ" - nóiTheFramework.MyClass
không hoạt động (trình biên dịch biết ý của bạn là gì , nhưng nó nói rằng nó không thể tìm thấy một lớp như vậy trong khung).
Kinh nghiệm của tôi là Swift do đó không được đặt tên trong một chút. Khi chuyển một trong những ứng dụng của tôi từ Objective-C sang Swift, tôi đã tạo ra một khung nhúng vì nó rất dễ thực hiện. Tuy nhiên, nhập khung, nhập tất cả nội dung Swift trong khung - vì vậy, một lần nữa, chỉ có một không gian tên và nó là toàn cầu. Và không có tiêu đề Swift để bạn không thể ẩn bất kỳ tên nào.
EDIT: Trong seed 3, tính năng này hiện đang bắt đầu xuất hiện trực tuyến, theo nghĩa sau: nếu mã chính của bạn chứa MyClass và khung của bạn MyFramework chứa MyClass, cái trước sẽ làm lu mờ cái sau theo mặc định, nhưng bạn có thể tiếp cận cái trong khung bằng cách sử dụng cú pháp MyFramework.MyClass
. Vì vậy, trên thực tế chúng ta có những sơ hở của một không gian tên riêng biệt!
EDIT 2: Trong hạt giống 4, bây giờ chúng ta có các điều khiển truy cập! Thêm vào đó, trong một trong những ứng dụng của tôi, tôi có một khung nhúng và chắc chắn, mọi thứ đều được ẩn theo mặc định và tôi phải phơi bày tất cả các bit của API công khai một cách rõ ràng. Đây là một cải tiến lớn.
Foundation.NSArray
.
Trong khi thực hiện một số thử nghiệm với điều này, cuối cùng tôi đã tạo ra các lớp "không gian tên" này trong các tệp riêng của chúng bằng cách mở rộng "gói" gốc. Không chắc chắn nếu điều này chống lại các thực tiễn tốt nhất hoặc nếu nó có bất kỳ hàm ý nào tôi biết về (?)
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)")
GóiOne.swift
import Foundation
struct PackageOne {
}
GóiTwo.swift
import Foundation
struct PackageTwo {
}
GóiOneClass.swift
extension PackageOne {
class Class {
var name: String
init(name:String) {
self.name = name
}
}
}
GóiTwoClass.swift
extension PackageTwo {
class Class {
var name: String
init(name:String) {
self.name = name
}
}
}
Biên tập:
Chỉ cần phát hiện ra rằng việc tạo "gói con" trong đoạn mã trên sẽ không hoạt động nếu sử dụng các tệp riêng biệt. Có lẽ ai đó có thể gợi ý về lý do tại sao đó là trường hợp?
Thêm các tệp sau vào phần trên:
GóiOneSubPackage.swift
import Foundation
extension PackageOne {
struct SubPackage {
}
}
GóiOneSubPackageClass.swift
extension PackageOne.SubPackage {
class Class {
var name: String
init(name:String) {
self.name = name
}
}
}
Nó gây ra lỗi trình biên dịch: 'SubPackage' không phải là loại thành viên của 'PackageOne'
Nếu tôi di chuyển mã từ GóiOneSubPackageClass.swift sang GóiOneSubPackage.swift thì nó hoạt động. Bất kỳ ai?
Chỉnh sửa 2:
Giải quyết vấn đề này và tìm ra (trong Xcode 6.1 beta 2) rằng bằng cách xác định các gói trong một tệp, chúng có thể được mở rộng trong các tệp riêng biệt:
public struct Package {
public struct SubPackage {
public struct SubPackageOne {
}
public struct SubPackageTwo {
}
}
}
Dưới đây là các tệp của tôi trong một ý chính: https://gist.github.com/mikajauhonen/d4b3e517122ad6a132b8
Tôi tin rằng điều này đạt được bằng cách sử dụng:
struct Foo
{
class Bar
{
}
}
Sau đó, nó có thể được truy cập bằng cách sử dụng:
var dds = Foo.Bar();
enum
, không phải a struct
, vì vậy bạn không thể khởi tạo a Foo
.
Swift sử dụng các mô-đun giống như trong python (xem tại đây và đây ) và như @Kevin Sylvestre đề xuất, bạn cũng có thể sử dụng các kiểu lồng nhau làm không gian tên.
Và để mở rộng câu trả lời từ @Daniel A. White, trong WWDC, họ đã nói về các mô-đun nhanh chóng.
Cũng ở đây được giải thích:
Các kiểu suy luận làm cho mã sạch hơn và ít bị lỗi hơn, trong khi các mô-đun loại bỏ các tiêu đề và cung cấp các không gian tên.
Không gian tên rất hữu ích khi bạn cần xác định lớp có cùng tên với lớp trong khung hiện có.
Giả sử ứng dụng của bạn có
MyApp
tên và bạn cần khai báo tùy chỉnh của mìnhUICollectionViewController
.
Bạn không cần phải thêm tiền tố và lớp con như thế này:
class MAUICollectionViewController: UICollectionViewController {}
Làm như thế này:
class UICollectionViewController {} //no error "invalid redeclaration o..."
Tại sao? . Bởi vì những gì bạn đã khai báo được khai báo trong mô-đun hiện tại , đó là mục tiêu hiện tại của bạn . Và UICollectionViewController
từ UIKit
được tuyên bố trongUIKit
mô-đun.
Làm thế nào để sử dụng nó trong mô-đun hiện tại?
var customController = UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
Làm thế nào để phân biệt chúng với một mô-đun khác?
var customController = MyApp.UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
Bạn có thể sử dụng extension
để sử dụng struct
cách tiếp cận được đề cập cho không gian tên mà không cần phải thụt lề tất cả các mã của bạn về phía bên phải. Tôi đã từng đùa giỡn với điều này một chút và tôi không chắc là tôi có thể tạo ra Controllers
vàViews
không gian tên như trong ví dụ dưới đây, nhưng nó minh họa cho việc nó có thể đi được bao xa:
Hồ sơ.swift :
// Define the namespaces
struct Profiles {
struct Views {}
struct ViewControllers {}
}
Hồ sơ / 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
}
}
Hồ sơ / Lượt xem / Edit.swift
extension Profiles.Views {
class Edit: UIView {}
}
extension Profiles.Views.Edit {
override func drawRect(rect: CGRect) {
// Do some stuff
}
}
Tôi chưa sử dụng điều này trong một ứng dụng vì tôi chưa cần mức độ tách biệt này nhưng tôi nghĩ đó là một ý tưởng thú vị. Điều này loại bỏ sự cần thiết của các hậu tố lớp chẵn như hậu tố phổ biến * ViewControll dài khó chịu.
Tuy nhiên, nó không rút ngắn bất cứ điều gì khi được tham chiếu, chẳng hạn như trong các tham số phương thức như thế này:
class MyClass {
func doSomethingWith(viewController: Profiles.ViewControllers.Edit) {
// secret sauce
}
}
Trong trường hợp bất kỳ ai cũng tò mò, kể từ ngày 10 tháng 6 năm 2014, đây là một lỗi đã biết trong Swift:
Từ SevenTenEleven
"Lỗi đã biết, xin lỗi! Rdar: // vấn đề / 17127940 Các loại Swift đủ điều kiện theo tên mô-đun của chúng không hoạt động."