gpt4 book ai didi

Swift:是否可以向协议(protocol)添加协议(protocol)扩展?

转载 作者:IT王子 更新时间:2023-10-29 05:35:55 24 4
gpt4 key购买 nike

假设我有两个协议(protocol):

protocol TheirPcol {}
protocol MyPcol {
func extraFunc()
}

我想要做的是为“TheirPcol”创建一个协议(protocol)扩展,让 extraFunc()处理任何符合“TheirPcol”的东西。所以像这样:
extension TheirPcol : MyPcol { // Error 'Extension of protocol 'TheirPcol' cannot have an inheritance clause.
func extraFunc() { /* do magic */}
}

struct TheirStruct:TheirPcol {}
let inst = TheirStruct()
inst.extraFunc()

这其中的关键是“TheirPcol”、“TheirStruct”都由我无法控制的外部 API 处理。所以我通过了实例“inst”。

这能做到吗?或者我将不得不做这样的事情:
struct TheirStruct:TheirPcol {}
let inst = TheirStruct() as! MyPcol
inst.extraFunc()

最佳答案

似乎有两个用例可以说明为什么您可能想要做您正在做的事情。在第一个用例中,Swift 将允许你做你想做的事,但在第二个用例中不是很干净。我猜你属于第二类,但我会同时进行。

扩展 TheirPcol 的功能

您可能想要这样做的原因之一只是为 TheirPcol 提供额外的功能。 .正如编译器错误所说,您不能扩展 Swift 协议(protocol)以符合其他协议(protocol)。但是,您可以简单地扩展 TheirPcol .

extension TheirPcol {
func extraFunc() { /* do magic */ }
}

在这里,您将提供符合 TheirPcol 的所有对象。方法 extraFunc()并为其提供默认实现。这完成了为符合 TheirPcol 的对象扩展功能的任务。 ,如果您希望它也适用于您自己的对象,那么您可以使您的对象符合 TheirPcol .但是,在许多情况下,您希望保留 MyPcol作为您的主要协议(protocol),只需对待 TheirPcol符合 MyPcol .不幸的是,Swift 目前不支持声明符合其他协议(protocol)的协议(protocol)扩展。

使用 TheirPcol对象就好像它们是 MyPcol
在您确实需要单独存在 MyPcol 的用例(很可能是您的用例)中,然后据我所知,还没有干净的方法可以做你想做的事。以下是一些有效但非理想的解决方案:

wrapper TheirPcol
一种潜在的困惑方法是使用 structclass像下面这样:
struct TheirPcolWrapper<T: TheirPcol>: MyPcol {
var object: T

func extraFunc() { /* Do magic using object */ }
}

从理论上讲,当您需要使现有对象实例符合 MyPcol 时,您可以将此结构用作强制转换的替代方法,如您的示例中所示。 .或者,如果您有接受 MyPcol 的函数作为通用参数,您可以创建接受 TheirPcol 的等效函数。 ,然后将其转换为 TheirPcolWrapper并将其发送到另一个函数接收 MyPcol .

另一件要注意的事情是,如果您正在传递一个对象 TheirPcol ,那么您将无法创建 TheirPcolWrapper实例而无需先将其转换为显式类型。这是由于 Swift 的一些泛型限制。因此,像这样的对象可能是另一种选择:
struct TheirPcolWrapper: MyPcol {
var object: MyPcol

func extraFunc() { /* Do magic using object */ }
}

这意味着您可以创建一个 TheirPcolWrapper不知道 TheirPcol 的显式类型的实例你得到了。

然而,对于一个大型项目,这两者都会很快变得困惑。

使用子协议(protocol)扩展单个对象

另一个非理想的解决方案是扩展每个您知道符合 TheirPcol 的对象。并且您知道您希望支持。例如,假设您知道 ObjectAObjectB符合 TheirPcol .您可以创建一个 MyPcol 的子协议(protocol)。然后显式声明两个对象的一致性,如下所示:
protocol BridgedToMyPcol: TheirPcol, MyPcol {}

extension BridgedToMyPcol {
func extraFunc() {
// Do magic here, given that the object is guaranteed to conform to TheirPcol
}
}

extension ObjectA: BridgedToMyPcol {}
extension ObjectB: BridgedToMyPcol {}

不幸的是,如果您希望支持大量对象,或者您无法提前知道这些对象是什么,那么这种方法就会失效。当您不知道 TheirPcol 的显式类型时,这也会成为一个问题。你得到了,虽然你可以使用 type(of:)得到一个元类型。

关于 Swift 4 的说明

您应该查看 Conditional conformances ,一个被 Swift 4 接受的提案。具体来说,这个提案概述了具有以下扩展的能力:
extension Array: Equatable where Element: Equatable {
static func ==(lhs: Array<Element>, rhs: Array<Element>) -> Bool { ... }
}

虽然这不是您要问的,但在底部您会找到“考虑的替代方案”,其中有一个名为“扩展协议(protocol)以符合协议(protocol)”的小节,这更多是您想要做的。它提供了以下示例:
extension Collection: Equatable where Iterator.Element: Equatable {
static func ==(lhs: Self, rhs: Self) -> Bool {
// ...
}
}

然后声明如下:

This protocol extension would make any Collection of Equatable elements Equatable, which is a powerful feature that could be put to good use. Introducing conditional conformances for protocol extensions would exacerbate the problem of overlapping conformances, because it would be unreasonable to say that the existence of the above protocol extension means that no type that conforms to Collection could declare its own conformance to Equatable, conditional or otherwise.



虽然我意识到您并没有要求具有条件一致性的能力,但这是我在讨论扩展协议(protocol)以符合其他协议(protocol)时能找到的最接近的事情。

关于Swift:是否可以向协议(protocol)添加协议(protocol)扩展?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41993616/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com