extension 中能增加存储属性吗?

extension :可以增加计算属性,不能增加存储属性。
extension是用来给存在的类型添加新行为的并不能改变类型或者接口本身。因为 extension 不能为类或结构体增加实际的存储空间。
(swift 没有分类的概念 只有extension扩展)

v[W 2025-10-29 00:51:22.136 ServerApp] A `_jupyter_server_extension_points` function was not found in jupyter_lsp. Instead, a `_jupyter_server_extension_paths` function was found and will be used for now. This function name will be deprecated in future releases of Jupyter Server. [W 2025-10-29 00:51:22.436 ServerApp] A `_jupyter_server_extension_points` function was not found in notebook_shim. Instead, a `_jupyter_server_extension_paths` function was found and will be used for now. This function name will be deprecated in future releases of Jupyter Server. [I 2025-10-29 00:51:25.260 ServerApp] Extension package panel.io.jupyter_server_extension took 2.8212s to import [I 2025-10-29 00:51:25.261 ServerApp] jupyter_lsp | extension was successfully linked. [I 2025-10-29 00:51:25.274 ServerApp] jupyter_server_terminals | extension was successfully linked. [I 2025-10-29 00:51:25.286 ServerApp] jupyterlab | extension was successfully linked. [I 2025-10-29 00:51:25.300 ServerApp] notebook | extension was successfully linked. [I 2025-10-29 00:51:26.305 ServerApp] notebook_shim | extension was successfully linked. [I 2025-10-29 00:51:26.305 ServerApp] panel.io.jupyter_server_extension | extension was successfully linked. [I 2025-10-29 00:51:26.407 ServerApp] notebook_shim | extension was successfully loaded. [I 2025-10-29 00:51:26.412 ServerApp] jupyter_lsp | extension was successfully loaded. [I 2025-10-29 00:51:26.413 ServerApp] jupyter_server_terminals | extension was successfully loaded. [I 2025-10-29 00:51:26.428 LabApp] JupyterLab extension loaded from C:\Users\wws\Anaconda3\Lib\site-packages\jupyterlab [I 2025-10-29 00:51:26.428 LabApp] JupyterLab application directory is C:\Users\wws\Anaconda3\share\jupyter\lab [I 2025-10-29 00:51:26.430 LabApp] Extension Manager is 'pypi'. [I 2025-10-29 00:51:26.432 ServerApp] jupyterlab | extension was successfully loaded. [I 2025-10-29 00:51:26.446 ServerApp] notebook | extension was successfully loaded. [I 2025-10-29 00:51:26.447 ServerApp] panel.io.jupyter_server_extension | extension was successfully loaded. [I 2025-10-29 00:51:26.448 ServerApp] Serving notebooks from local directory: C:\Users\wws [I 2025-10-29 00:51:26.448 ServerApp] Jupyter Server 2.14.1 is running at: [I 2025-10-29 00:51:26.448 ServerApp] http://localhost:8888/tree?token=214a25ae7e7bb21324a86592d61c7ba73fb82b965d5a0d48 [I 2025-10-29 00:51:26.449 ServerApp] http://127.0.0.1:8888/tree?token=214a25ae7e7bb21324a86592d61c7ba73fb82b965d5a0d48 [I 2025-10-29 00:51:26.449 ServerApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation). [E 2025-10-29 00:51:26.449 ServerApp] Failed to write server-info to C:\Users\wws\AppData\Roaming\jupyter\runtime\jpserver-102284.json: PermissionError(13, 'Permission denied') Traceback (most recent call last): File "C:\Users\wws\Anaconda3\Scripts\jupyter-notebook-script.py", line 10, in sys.exit(main()) ^^^^^^ File "C:\Users\wws\Anaconda3\Lib\site-packages\jupyter_server\extension\application.py", line 623, in launch_instance serverapp.start() File "C:\Users\wws\Anaconda3\Lib\site-packages\jupyter_server\serverapp.py", line 3119, in start self.start_app() File "C:\Users\wws\Anaconda3\Lib\site-packages\jupyter_server\serverapp.py", line 3023, in start_app self.write_browser_open_files() File "C:\Users\wws\Anaconda3\Lib\site-packages\jupyter_server\serverapp.py", line 2890, in write_browser_open_files self.write_browser_open_file() File "C:\Users\wws\Anaconda3\Lib\site-packages\jupyter_server\serverapp.py", line 2913, in write_browser_open_file with open(self.browser_open_file, "w", encoding="utf-8") as f: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PermissionError: [Errno 13] Permission denied: 'C:\\Users\\wws\\AppData\\Roaming\\jupyter\\runtime\\jpserver-102284-open.html'
10-30
你问得非常好,我们来一步步澄清几个关键概念: > ❓ “所以 extension 里面都是局部变量?” > ❓ “如果我需要外部修改我的未读数呢?” 这两个问题涉及 **Swift 的作用域、访问控制和模块化设计**。下面我们逐个解答。 --- ## ✅ 回答第一个问题: ### ❌ “extension 里面都是局部变量” —— 这是误解! ### 🔹 正确认知: > `extension`(扩展)不是“局部作用域”,它和原类型在同一个命名空间中,可以添加: - 新的计算属性 - 方法 - 存储属性(通过关联对象) - 嵌套类型 这些成员**不是局部变量**,而是**类型的一部分**! --- ### ✅ 示例:Extension 添加非局部成员 ```swift class SidebarViewController: NSViewController { // 原始类 } // 扩展添加方法和属性 extension SidebarViewController { private var unreadCount: Int = 0 // ✅ 是实例属性,不是局部变量! func updateUnreadCount(_ count: Int) { self.unreadCount = count print("未读消息数更新为: $count)") } } ``` 📌 注意: - `unreadCount` 是这个类的一个私有存储属性(虽然 Swift 不支持直接在 extension添加存储属性,但我们可以通过 `associatedObject` 实现,稍后说明) - `updateUnreadCount(_:)` 是一个公开方法,可以在别处调用 👉 所以:**`extension` 内部定义的成员属于类型本身,不是局部变量!** --- ## ✅ 回答第二个问题: ### 🎯 “如果我需要外部修改我的未读数呢?” 你需要一个 **可被外界访问或修改的接口**。 这里有几种方式,根据你的需求选择: --- ## ✅ 方案一:使用 `internal` 或 `public` 属性 + 方法(推荐) ```swift class SidebarViewController: NSViewController { // 默认 internal,同一模块内可访问 private(set) var unreadCount: Int = 0 // 外部只能读,不能写 func setUnreadCount(_ count: Int) { self.unreadCount = count updateUI() // 同时刷新 UI } private func updateUI() { // 更新 label 显示 statusLabel?.stringValue = "($unreadCount)" } } ``` 然后在其他地方调用: ```swift sidebarVC.setUnreadCount(5) // ✅ 外部可以修改 print(sidebarVC.unreadCount) // ✅ 可读 ``` ✅ 优点: - 封装性好 - 控制谁可以改、谁只能读 - 可以附带副作用(如刷新 UI) --- ## ✅ 方案二:使用 `@Published` + Observable Object(适合 SwiftUI / Combine) 如果你用 Combine 或 SwiftUI 风格: ```swift import Combine class SidebarViewModel: ObservableObject { @Published var unreadCount: Int = 0 } // 外部修改 viewModel.unreadCount = 10 ``` --- ## ✅ 方案三:使用通知中心 NotificationCenter(松耦合) 适用于跨组件通信: ```swift // 发送通知 NotificationCenter.default.post( name: .unreadCountDidChange, object: nil, userInfo: ["count": 5] ) // 在 SidebarViewController 中监听 extension SidebarViewController { override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver( self, selector: #selector(handleUnreadCountChange(_:)), name: .unreadCountDidChange, object: nil ) } @objc private func handleUnreadCountChange(_ notification: Notification) { if let count = notification.userInfo?["count"] as? Int { self.unreadCount = count updateUI() } } } ``` ✅ 优点:解耦;缺点:难调试 --- ## ✅ 方案四:协议回调(Delegate Pattern) 定义一个协议让别人通知你: ```swift protocol UnreadCountDelegate: AnyObject { func didUpdateUnreadCount(to count: Int) } class SidebarViewController: NSViewController, UnreadCountDelegate { func didUpdateUnreadCount(to count: Int) { self.unreadCount = count updateUI() } } ``` --- ## ⚠️ 特别注意:如何在 extension 中真正“添加存储属性”? Swift 默认不允许在 extension添加存储属性,但你可以用 **关联对象(Associated Object)** 模拟: ```swift import ObjectiveC private var AssociatedUnreadKey: UInt8 = 0 extension SidebarViewController { var unreadCount: Int { get { return objc_getAssociatedObject(self, &AssociatedUnreadKey) as? Int ?? 0 } set { objc_setAssociatedObject(self, &AssociatedUnreadKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) updateUI() } } } ``` ⚠️ 注意: - 这种方式有一定风险(内存管理、线程安全) - 推荐仅在必须的情况下使用 - 更好的方式是:把属性放在主类中,extension 只放方法 --- ## ✅ 总结 | 问题 | 正确理解 | |------|----------| | `extension` 是局部作用域吗? | ❌ 不是!它是类型的扩展,可以添加方法、计算属性等 | | 能在 extension 里定义变量吗? | ❌ 不能直接加存储属性,但可以用 `associatedObject` 模拟 | | 外部怎么修改未读数? | ✅ 提供 `setUnreadCount(_:)` 方法 或 使用 `@Published` / 通知中心等机制 | | 如何保证封装性和安全性? | ✅ 使用 `private(set)` 让外部只读,内部可写 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值