我想表达一个类似于以下两个片段的Swift协议,这两个片段都无法编译。
尝试1:
protocol AbstractFunction {
associatedtype Domain
associatedtype Codomain
func apply(_ x: Domain) -> Codomain
static var identity: Self where Domain == Codomain { get }
}
尝试2:
protocol AbstractFunction {
associatedtype Domain
associatedtype Codomain
func apply(_ x: Domain) -> Codomain
static func identity() -> Self where Domain == Codomain { get }
}
第一个在Swift语法中甚至不是有效的,而第二个在'where' clause cannot be attached to a non-generic declaration
中失败。
这两个示例都试图表达一种协议,该协议描述的函数不是实际函数类型(A) -> B
的实例。如果有一个类型Vector2
和Vector3
,可以想象创建类型Matrix2x2
,Matrix2x3
和Matrix3x3
并使它们符合AbstractFunction
协议。 MatrixNxM
的领域是VectorM
,而codomain将是VectorN
。方形矩阵具有单位矩阵,但是当域和密码域不同时,单位矩阵(或真正的身份函数)的概念没有意义。
因此,我希望协议AbstractFunction
要求符合类型提供身份,但仅限于Domain == Codomain
的情况。这可能吗?
您可以通过声明第二个更严格的协议来实现它:
protocol AbstractFunction {
associatedtype Domain
associatedtype Codomain
func apply(_ x: Domain) -> Codomain
}
protocol AbstractEndofunction: AbstractFunction where Codomain == Domain {
static var identity: Self { get }
}
Int - > Int函数示例:
final class IntFunction: AbstractEndofunction {
typealias Domain = Int
static var identity = IntFunction { $0 }
private let function: (Int) -> Int
init(_ function: @escaping (Int) -> Int) {
self.function = function
}
func apply(_ x: Int) -> Int {
return function(x)
}
}
我认为你不能这样做。但是,我可以看到另外两种方法可以帮助你。
通过对identity
使用可选类型,您可以指出实现AbstractFunction
的某种类型可能具有或不具有标识。例如:
final class ConcreteFunctionWithoutIdentity: AbstractFunction {
typealias Domain = Int
typealias Codomain = Int
func apply(_ x: Int) -> Int {
return 0
}
static var identity: ConcreteFunctionWithoutIdentity?
}
// Using
if let identity = ConcreteFunctionWithoutIdentity.identity else {
// It will not fall here, since ConcreteFunctionWithoutIdentity doesn't have identity
...
}
final class ConcreteFunctionWithIdentity: AbstractFunction {
typealias Domain = Int
typealias Codomain = Int
func apply(_ x: Int) -> Int {
return 0
}
static var identity: ConcreteFunctionWithtIdentity? {
// return something
}
}
if let identity = ConcreteFunctionWithtIdentity.identity else {
// It will fall here, since ConcreteFunctionWithIdentity indeed have identity
...
}