当前位置: 首页 > 面试题库 >

是否可以向Swift协议一致性扩展中添加类型约束?

陆海阳
2023-03-14
问题内容

我想扩展Array以增加对新协议的一致性-但仅适用于其元素本身符合特定协议的数组

更笼统地说,我想让带有类型参数的类型(无论是协议类型还是具体类型)仅在类型参数与某些约束匹配时才实现协议。

从Swift 2.0开始,这似乎是不可能的。有什么我想念的方式吗?

假设我们有以下Friendly协议:

protocol Friendly {
    func sayHi()
}

我们可以扩展现有的类型来实现它:

extension String: Friendly {
    func sayHi() {
        print("Greetings from \(self)!")
    }
}

"Sally".sayHi()

我们还可以扩展Array实现sayHi()其所有元素时的实现Friendly

extension Array where Element: Friendly {
    func sayHi() {
        for elem in self {
            elem.sayHi()
        }
    }
}

["Sally", "Fred"].sayHi()

在这一点上,类型[Friendly]本身应该实现Friendly,因为它符合协议的要求。 但是,此代码无法编译

extension Array: Friendly where Element: Friendly {
    func sayHi() {
        for elem in self {
            elem.sayHi()
        }
    }
}

错误消息是“具有约束的’Array’类型的扩展不能具有继承子句”,这似乎最终确定了直接方法的大门。

有间接解决方法吗? 我可以使用一些巧妙的技巧?也许有一种方法涉及扩展 SequenceType而不是 Array

一个可行的解决方案将使此代码编译:

let friendly: Friendly = ["Foo", "Bar"]

更新: 它已落入Swift 4.1中,真是太美了!

extension Array: Friendly where Element: Friendly现在,该示例将按照原始问题中的说明进行编译。


问题答案:

编辑:如更新的问题中所述,自Swift 4.1起,现在可以实现

目前在Swift中(从Xcode
7.1开始)无法实现。如错误所示,您不能将协议一致性(“继承子句”)限制为类型受限的扩展。也许有一天。我不认为没有任何可能的深层原因,但是目前尚未实现。

您可以获得的最接近的结果是创建一个包装器类型,例如:

struct FriendlyArray<Element: Friendly>: Friendly {
    let array: [Element]
    init(_ array: [Element]) {
        self.array = array
    }
    func sayHi() {
        for elem in array {
            elem.sayHi()
        }
    }
}

let friendly: Friendly = FriendlyArray(["Foo", "Bar"])

(您可能想扩展FriendlyArray为一个CollectionType。)

有关我自己陷入尝试进行这项工作的疯狂以及我从边缘爬回的故事,请参阅NSData,我的老朋友。



 类似资料:
  • 问题内容: 可以说我有两个协议: 我想要做的是为“ TheirPcol”创建一个协议扩展,该协议扩展允许在符合“ TheirPcol”的任何事物上工作。所以像这样: 关键是“ TheirPcol”,“ TheirStruct”全部由我无法控制的外部API处理。因此,我通过了实例“ inst”。 能做到吗?还是我必须做这样的事情: 问题答案: 似乎有两个用例说明为什么您想做自己正在做的事情。在第一个

  • 问题内容: 假设我有以下协议: 而且我有以下结构: 如您所见,我必须“遵循”结构A和结构B中的Identifiable协议。但是想象一下,如果我还有N个需要符合该协议的结构……我不想“复制/粘贴” ‘一致性(变量ID:整数,变量名称:字符串) 所以我创建了一个 协议扩展 : 现在,通过此扩展,我可以创建符合Identifiable协议的结构,而不必同时实现这两个属性: 现在的问题是我不能为id属性

  • 问题内容: 我正在尝试使用Swift协议扩展,却发现这种行为令人困惑。您能帮我得到我想要的结果吗? 请参阅代码最后4行的注释。(如果需要,可以将其复制粘贴到Xcode7游乐场)。谢谢!! 问题答案: 简短的答案是协议扩展不执行类多态性。这是有一定道理的,因为协议可以被结构或枚举采用,并且因为我们不希望仅在没有必要的地方采用协议来引入动态调度。 因此,在中,实例变量(可能更准确地写为)并不意味着您认

  • 问题内容: protocol BasePresenterProtocol : class {} protocol DashboardPresenterProtocol : BasePresenterProtocol {} 在上面的代码中,我在下一行收到错误 ,但未确认协议,但我已在中声明。虽然我已经宣布 为什么会出现此错误?请让我知道我在这段代码中做错了什么。 问题答案: 您不能使用type 属性

  • 问题内容: 我有两个表,并添加了外键约束。海螺-效果很好。现在,是否可以针对父表中的某些数据进一步限制这种关系? 基本上,我在父表中有动物,而对于子表,希望仅包含父数据为.... um ..哺乳动物的数据。 例如。 因此,我希望确保AnimalId只能是Animals.AnimalType = 1类型 这可能吗?? 我不想让某人尝试在子表中插入一些针对爬行动物的信息… 干杯:) 编辑: 我以为我必

  • 问题内容: 我是否可以制作仅适用于字符串的Array扩展? 问题答案: 从Swift 2开始,这可以通过 协议扩展 来实现,该 协议扩展 为符合类型的类型(可选地受其他约束限制)提供方法和属性实现。 一个简单的例子:为所有符合(例如)的类型定义一个方法,其中sequence元素为: 不能直接为扩展方法定义扩展方法,而只能为符合某种协议(带有可选约束)的所有类型定义扩展方法。因此,必须找到一种协议,