将通用结构与协议一起使用
Use generic struct with protocol
似乎 Swift 泛型工作正常,只要我不尝试以任何实际方式组合它们。我正在使用 Swift 4.1,我想创建一个仅包含弱引用的通用数组。我可以将其定义为 WeakList<T>
。到目前为止一切顺利。但是:我想使用 T
的协议。 Swift 说不..
import Foundation
protocol Observer: class {
func stateChanged(sender: SomeClass, newState: Int)
}
struct WeakList<T> where T: AnyObject {
struct Ptr {
weak var p: T?
}
private var storage: [Ptr] = []
var aliveObjects: [T] {
var result: [T] = []
for ptr in storage {
if let p = ptr.p {
result.append(p)
}
}
return result
}
mutating func add(_ obj: T) {
storage.append(Ptr(p: obj))
}
// Let's ignore for a moment that this implementation leaks memory badly.
}
class SomeClass {
var someVar: WeakList<Observer> = WeakList<Observer>()
// Error: WeakList requires that 'Observer' be a class type
var thisIsOk: WeakList<NSObject> = WeakList<NSObject>()
}
(这不是我的原始代码,而是一个包含足够细节的最小可验证示例,因此没有人可以说 "just remove the AnyObject constraint from the structure")
我想我想做的事情是不可能的。或者是吗?令人沮丧的是,当我尝试使用 Swift 泛型做某事时,有 5 次中有 4 次,我后来才知道我正在尝试做的事情是不可能的。 (顺便说一句,我可以很容易地在 Objective-C 中实现同样的事情。)
- 我尝试将
class
约束更改为 AnyObject
约束 => 也不起作用。
- 我试图将
AnyObject
约束更改为 class
约束 => 甚至无法编译。
- 并将其更改为
protocol Observer where Self: NSObject
不会改变任何内容。 NSObject
是 class 类型,Observer
是 NSObject
类型。应该遵循 Observer
是 class 类型。 "is a" 关系在这里似乎没有传递性。
在当前的实现中,您无法从 AnyObject
继承协议。你可以做的是为你的协议创建一个类型橡皮擦,然后使用它。现在你的类型橡皮擦可以继承自 AnyObject
.
像这样:
protocol Observer {
func stateChanged(sender: SomeClass, newState: Int)
}
class AnyObserver: NSObject, Observer {
private let observer: Observer
init(observer: Observer) {
self.observer = observer
}
func stateChanged(sender: SomeClass, newState: Int) {
observer.stateChanged(sender: sender, newState: newState)
}
}
struct WeakList<T> where T: AnyObject {
struct Ptr {
weak var p: T?
}
private var storage: [Ptr] = []
var aliveObjects: [T] {
var result: [T] = []
for ptr in storage {
if let p = ptr.p {
result.append(p)
}
}
return result
}
mutating func add(_ obj: T) {
storage.append(Ptr(p: obj))
}
// Let's ignore for a moment that this implementation leaks memory badly.
}
class SomeClass {
var someVar: WeakList<AnyObserver> = WeakList<AnyObserver>()
var thisIsOk: WeakList<NSObject> = WeakList<NSObject>()
}
似乎 Swift 泛型工作正常,只要我不尝试以任何实际方式组合它们。我正在使用 Swift 4.1,我想创建一个仅包含弱引用的通用数组。我可以将其定义为 WeakList<T>
。到目前为止一切顺利。但是:我想使用 T
的协议。 Swift 说不..
import Foundation
protocol Observer: class {
func stateChanged(sender: SomeClass, newState: Int)
}
struct WeakList<T> where T: AnyObject {
struct Ptr {
weak var p: T?
}
private var storage: [Ptr] = []
var aliveObjects: [T] {
var result: [T] = []
for ptr in storage {
if let p = ptr.p {
result.append(p)
}
}
return result
}
mutating func add(_ obj: T) {
storage.append(Ptr(p: obj))
}
// Let's ignore for a moment that this implementation leaks memory badly.
}
class SomeClass {
var someVar: WeakList<Observer> = WeakList<Observer>()
// Error: WeakList requires that 'Observer' be a class type
var thisIsOk: WeakList<NSObject> = WeakList<NSObject>()
}
(这不是我的原始代码,而是一个包含足够细节的最小可验证示例,因此没有人可以说 "just remove the AnyObject constraint from the structure")
我想我想做的事情是不可能的。或者是吗?令人沮丧的是,当我尝试使用 Swift 泛型做某事时,有 5 次中有 4 次,我后来才知道我正在尝试做的事情是不可能的。 (顺便说一句,我可以很容易地在 Objective-C 中实现同样的事情。)
- 我尝试将
class
约束更改为AnyObject
约束 => 也不起作用。 - 我试图将
AnyObject
约束更改为class
约束 => 甚至无法编译。 - 并将其更改为
protocol Observer where Self: NSObject
不会改变任何内容。NSObject
是 class 类型,Observer
是NSObject
类型。应该遵循Observer
是 class 类型。 "is a" 关系在这里似乎没有传递性。
在当前的实现中,您无法从 AnyObject
继承协议。你可以做的是为你的协议创建一个类型橡皮擦,然后使用它。现在你的类型橡皮擦可以继承自 AnyObject
.
像这样:
protocol Observer {
func stateChanged(sender: SomeClass, newState: Int)
}
class AnyObserver: NSObject, Observer {
private let observer: Observer
init(observer: Observer) {
self.observer = observer
}
func stateChanged(sender: SomeClass, newState: Int) {
observer.stateChanged(sender: sender, newState: newState)
}
}
struct WeakList<T> where T: AnyObject {
struct Ptr {
weak var p: T?
}
private var storage: [Ptr] = []
var aliveObjects: [T] {
var result: [T] = []
for ptr in storage {
if let p = ptr.p {
result.append(p)
}
}
return result
}
mutating func add(_ obj: T) {
storage.append(Ptr(p: obj))
}
// Let's ignore for a moment that this implementation leaks memory badly.
}
class SomeClass {
var someVar: WeakList<AnyObserver> = WeakList<AnyObserver>()
var thisIsOk: WeakList<NSObject> = WeakList<NSObject>()
}