我正在尝试在Swift中实现通用的flyweight模式。在我的代码中,我使用的是弱引用字典。基本协议(Node
)仅具有位置。更改位置会创建一个新的Node
。
当不再有对给定重量的引用时,我在网上看到的实现方式不会尝试清理问题。
符合Node
的类可以选择使用Factory
进行flyweighting,它维护现有对象的字典。
Weak<T>.hash(into:)
)。这会破坏一切吗?deinit
的工厂中删除这些值?我能以一般方式做到吗?===
不能用于协议类型。我可以通过测试以某种方式解决这个问题吗?完整的游乐场代码
import Foundation
protocol Node {
// Immutable: changing the position returns a new node
func position(_ p:CGPoint) -> Node
func printAddress()
}
protocol HashableNode : class, Hashable, Node { }
struct Weak<T : HashableNode> : Hashable {
static func == (lhs: Weak<T>, rhs: Weak<T>) -> Bool {
return lhs.value == rhs.value
}
weak var value : T?
func hash(into hasher: inout Hasher) {
value?.hash(into: &hasher)
}
}
class Factory<T:HashableNode> {
var values = [Weak<T> : Weak<T>]()
func make(_ proto: T) -> T {
let w = Weak<T>(value: proto)
if let v = values[w] {
if let r = v.value {
return r
}
}
values[w] = w
return proto
}
}
class TestNode : HashableNode {
deinit {
print("TestNode deinit")
}
// Can I define equality and hash automatically?
static func == (lhs: TestNode, rhs: TestNode) -> Bool {
return lhs.p == rhs.p
}
func hash(into hasher: inout Hasher) {
hasher.combine(p.x)
hasher.combine(p.y)
}
let p:CGPoint
init(p: CGPoint) {
print("TestNode init")
self.p = p
}
func position(_ p: CGPoint) -> Node {
return testNodeFactory.make(TestNode(p: p))
}
func printAddress() {
print(Unmanaged.passUnretained(self).toOpaque())
}
}
let testNodeFactory = Factory<TestNode>()
func runTest() {
let n0 = testNodeFactory.make(TestNode(p: CGPoint.zero))
let n1 = testNodeFactory.make(TestNode(p: CGPoint.zero))
assert(n0 === n1)
n0.printAddress()
n1.printAddress()
let n2 = n0.position(CGPoint(x: 1, y: 1))
n2.printAddress()
// Doesn't compile:
// Binary operator '!==' cannot be applied to operands of type 'Node' and 'TestNode'
// assert(n2 !== n0)
}
runTest()
print("done!")
答案 0 :(得分:2)
此行:
from itertools import islice
def qud(x,p):
x_sqr = x**2
x_qud = x**3
while True:
p = x_sqr*p # update p
yield x_sqr ,x_qud,p # yield instead of return
my_iterator = qud(2,1/2) # create an iterator based on itial values
for values in islice(my_iterator, 0, 4): # loop over an islice
print(values)
此处调用的position方法将返回let n2 = n0.position(CGPoint(x: 1, y: 1))
,而不是您为Node
和TestNode
明确创建的n1
。编译器不知道如何比较这两种类型。
您可以为TestNode <-> Node实现n2
或将cast n2键入为TestNode