如何为仅适用于 Swift 4.1 中的可选泛型参数的泛型结构创建扩展?
How to create extension for a generic structure that will be available only for Optional generic parameters in Swift 4.1?
我的 iOS 应用程序中有以下结构:
struct MyStruct<T> {
var property1: T
var property2: T
init(property1: T, property2: T) {
self.property1 = property1
self.property2 = property2
}
init(allPropertiesWith value: T) {
self.property1 = value
self.property2 = value
}
}
我也有 2 个 类 没有共同的祖先:
class A { }
class B { }
在我的应用程序中,我有 MyStruct<A>
、MyStruct<B>
、MyStruct<A?>
、MyStruct<B?>
的实例,我在这些函数中使用它们:
func f1(myStrurct: MyStruct<A?>) { }
func f2(myStrurct: MyStruct<A>) { }
func g2() {
f1(myStrurct: MyStruct<A?>(property2: A()))
}
/* I also have the same functions for MyStruct<B> and MyStruct<B?> */
我无法修改 f1
、f2
和 g2
。这就是为什么我创建了 2 个扩展来简化 MyStruct<T>
的初始化:
extension MyStruct where T == A? {
init(property1: T) {
self.property1 = property1
self.property2 = nil
}
init(property2: T) {
self.property1 = nil
self.property2 = property2
}
}
extension MyStruct where T == B? {
init(property1: T) {
self.property1 = property1
self.property2 = nil
}
init(property2: T) {
self.property1 = nil
self.property2 = property2
}
}
如您所见,这些扩展名几乎相同。是否可以只用 1 个扩展来重构它?
您可以使 A
和 B
(或任何 class 需要它)都符合 虚拟协议 并检查是否T
.
protocol MyStructProtocol {
}
class A: MyStructProtocol { }
class B: MyStructProtocol { }
extension MyStruct where T == MyStructProtocol? {
init(property1: T) {
self.property1 = property1
self.property2 = nil
}
init(property2: T) {
self.property1 = nil
self.property2 = property2
}
}
您无需扩展任何内容即可创建如此简单的构造函数。在下面查看结构定义的修改版本:
struct MyStruct<T> {
var property1: T?
var property2: T?
init(property1: T? = nil, property2: T? = nil) {
if T.self == String.self {
self.property1 = property1
self.property2 = nil
}
else if T.self == Int.self {
self.property1 = nil
self.property2 = property2
}
}
init(allPropertiesWith value: T) {
self.property1 = value
self.property2 = value
}
}
然后您可以根据需要使用以下几行初始化它们。
MyStruct<String>(property2: "sadsad")
MyStruct<Int>(property1: 23)
在 provided by Rakesha Shastri 中我发现我可以使用 protocol
来重构我的代码。但是,为了能够使用此解决方案,我需要重写应用程序的其他部分。我尝试将 Rakesha Shastri 的解决方案添加到我的应用程序中,并使用 Swift 3、Swift 4 或 Swift 4.2(所有 Swift 版本在 Xcode 10.0),但每次我都会收到编译错误。这意味着目前没有办法解决我在这个问题中描述的问题。
我的 iOS 应用程序中有以下结构:
struct MyStruct<T> {
var property1: T
var property2: T
init(property1: T, property2: T) {
self.property1 = property1
self.property2 = property2
}
init(allPropertiesWith value: T) {
self.property1 = value
self.property2 = value
}
}
我也有 2 个 类 没有共同的祖先:
class A { }
class B { }
在我的应用程序中,我有 MyStruct<A>
、MyStruct<B>
、MyStruct<A?>
、MyStruct<B?>
的实例,我在这些函数中使用它们:
func f1(myStrurct: MyStruct<A?>) { }
func f2(myStrurct: MyStruct<A>) { }
func g2() {
f1(myStrurct: MyStruct<A?>(property2: A()))
}
/* I also have the same functions for MyStruct<B> and MyStruct<B?> */
我无法修改 f1
、f2
和 g2
。这就是为什么我创建了 2 个扩展来简化 MyStruct<T>
的初始化:
extension MyStruct where T == A? {
init(property1: T) {
self.property1 = property1
self.property2 = nil
}
init(property2: T) {
self.property1 = nil
self.property2 = property2
}
}
extension MyStruct where T == B? {
init(property1: T) {
self.property1 = property1
self.property2 = nil
}
init(property2: T) {
self.property1 = nil
self.property2 = property2
}
}
如您所见,这些扩展名几乎相同。是否可以只用 1 个扩展来重构它?
您可以使 A
和 B
(或任何 class 需要它)都符合 虚拟协议 并检查是否T
.
protocol MyStructProtocol {
}
class A: MyStructProtocol { }
class B: MyStructProtocol { }
extension MyStruct where T == MyStructProtocol? {
init(property1: T) {
self.property1 = property1
self.property2 = nil
}
init(property2: T) {
self.property1 = nil
self.property2 = property2
}
}
您无需扩展任何内容即可创建如此简单的构造函数。在下面查看结构定义的修改版本:
struct MyStruct<T> {
var property1: T?
var property2: T?
init(property1: T? = nil, property2: T? = nil) {
if T.self == String.self {
self.property1 = property1
self.property2 = nil
}
else if T.self == Int.self {
self.property1 = nil
self.property2 = property2
}
}
init(allPropertiesWith value: T) {
self.property1 = value
self.property2 = value
}
}
然后您可以根据需要使用以下几行初始化它们。
MyStruct<String>(property2: "sadsad")
MyStruct<Int>(property1: 23)
在 protocol
来重构我的代码。但是,为了能够使用此解决方案,我需要重写应用程序的其他部分。我尝试将 Rakesha Shastri 的解决方案添加到我的应用程序中,并使用 Swift 3、Swift 4 或 Swift 4.2(所有 Swift 版本在 Xcode 10.0),但每次我都会收到编译错误。这意味着目前没有办法解决我在这个问题中描述的问题。