[英]How to implement a infix custom operator that handles optionality in swift
[英]How to implement a default method for a custom infix operator in a protocol extension
我正在嘗試將自定義比較中綴運算符==^
實現為標准相等運算符==
的精簡版本
我的應用程序主要面向協議,因此我試圖在協議擴展中實現默認方法static func ==^
。 然而,當我讓我的 class 符合協議時,我得到一個Type 'MySourceNode' does not conform to protocol 'SourceNodeType'
錯誤,並且 Xcode 讓我添加static func ==^
協議 5
我的問題是,如何在協議擴展中正確編寫默認實現?
我試圖在 SO 上找到答案,但其中大多數都比較老,並且只討論在協議擴展之外定義的通用方法。 但這在我的情況下似乎不起作用。
這是一個游樂場文件,其中包含我的協議的簡化版本。 代碼后有一些背景信息。 如果有不清楚的地方,請在評論中告訴我,我會相應地更新我的問題。
import Foundation
import SpriteKit
infix operator ==^: ComparisonPrecedence
protocol SourceNodeType: SKShapeNode {
var constrainZRotation: SKConstraint! { get set }
func setConstraints()
static func ==^ (lhs: SourceNodeType, rhs: SourceNodeType) -> Bool
}
extension SourceNodeType {
func setConstraints() {
print("Setting constraints")
}
static func ==^ (lhs: SourceNodeType, rhs: SourceNodeType) -> Bool {
lhs.frame == rhs.frame &&
lhs.position == rhs.position &&
lhs.constrainZRotation == rhs.constrainZRotation
}
}
class MySourceNode: SKShapeNode, SourceNodeType {
var constrainZRotation: SKConstraint!
}
解釋這個自定義中綴運算符背后的原因。 我需要它,因為我經常將 SpriteKit 的 SKShapeNodes 的子類相互比較。 但我不希望 class 中的每個變量(如可訪問性 label 或名稱)都進行比較,因為我在將節點添加到場景時更改了這些值,這部分是在比較之后。
我意識到將func ==^
方法放在協議之外,並且僅使用SourceNodeType
協議將其實現為rhs
和lhs
類型正是我所需要的!
這個答案解決了我的問題:
https://stackoverflow.com/a/41390111/12764795
也許有人可以確認這是 go 的當前正確方法?
import Foundation
import SpriteKit
infix operator ==^: ComparisonPrecedence
func ==^ (lhs: SourceNodeType, rhs: SourceNodeType) -> Bool {
lhs.frame == rhs.frame &&
lhs.position == rhs.position &&
lhs.constrainZRotation == rhs.constrainZRotation
}
protocol SourceNodeType: SKShapeNode {
var constrainZRotation: SKConstraint! { get set }
func setConstraints()
}
extension SourceNodeType {
func setConstraints() {
print("Setting constraints")
}
}
class MySourceNode: SKShapeNode, SourceNodeType {
var constrainZRotation: SKConstraint!
}
let lhsSourceNode = MySourceNode(circleOfRadius: 10)
var rhsSourceNode = MySourceNode(circleOfRadius: 10)
print(lhsSourceNode ==^ rhsSourceNode) // TRUE
rhsSourceNode.name = "Name used for testing"
print(lhsSourceNode ==^ rhsSourceNode) // TRUE
rhsSourceNode.position.y += 100
print(lhsSourceNode ==^ rhsSourceNode) // FALSE
問題是,您無法滿足這種協議要求:
static func ==^ (lhs: SourceNodeType, rhs: SourceNodeType) -> Bool
我在Swift 文檔中找不到明確的解釋,但是如果您嘗試使類型符合該協議,它將無法編譯,也不應該編譯。
我的問題是,如何在協議擴展中正確編寫默認實現?
如果要使用SourceNodeType
類型的參數,使用免費的 function 是最直接的方法,但刪除操作員要求會使編譯器錯誤靜音,即:
protocol SourceNodeType: SKShapeNode {
var constrainZRotation: SKConstraint! { get set }
func setConstraints()
}
直到您嘗試使用您的運營商:
let node = MySourceNode()
let otherNode = MySourceNode()
node ==^ otherNode // Generic parameter 'Self' could not be inferred
您仍然可以通過聲明以下內容來解決此問題:
extension SourceNodeType {
static func ==^ (lhs: Self, rhs: SourceNodeType) -> Bool {
lhs.frame == rhs.frame &&
lhs.position == rhs.position &&
lhs.constrainZRotation == rhs.constrainZRotation
}
}
它將按預期工作,但您仍然無法將其聲明為協議要求,因為它會觸發:
協議“SourceNodeType”只能用作通用約束,因為它具有 Self 或關聯的類型要求
由於 rhs 是SourceNodeType
類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.