gpt4 book ai didi

swift - 扩展协议(protocol)以实现不同的行为

转载 作者:搜寻专家 更新时间:2023-10-31 08:25:10 25 4
gpt4 key购买 nike

Swift 问题,比如说你有一个协议(protocol) Bark:

protocol MakeSound {
func bark()
}

一个父类(super class) Dog,实现了吠叫和游泳:

class Dog: MakeSound {
}

然后是不同类型的狗:

class Poodle: Dog {
}

class GermanShephard: Dog {
}

class SheepDog: Dog {
}

但是 Poodle 会狂吠,它们不会吠叫……所有的狗都会吠叫,只是它们的叫法不同……我如何赋予它们特定的吠叫行为?

扩展协议(protocol)?...

extension MakeSound {
func bark()
func yapper()
}

但是 Poodle 和德国牧羊犬都有这两种行为(一只狂吠的德国牧羊犬?!)

如果我进行 2 次扩展并使用 where Self = ? 检查类型类

extension MakeSound where Self: GermanShephard {
func bark() {
print("Bark")
}
}

extension MakeSound where Self: Poodle{
func yapper() {
print("yap yap")
}
}

但我只能检查一种类类型或狗类型。牧羊犬也会吠叫,但我无法在此处查看...

我知道在 Java 中,您可以使用多种不同的实现来扩展接口(interface)。你如何在 Swift 中使用协议(protocol)来解决这个问题?

最佳答案

如果我正确理解你的问题,也许这对你有帮助。

您可以通过扩展协议(protocol)为 bark() 提供默认实现。然后在符合协议(protocol)的其他类上,您可以更改 bark 函数的实现:

protocol Bark {
func bark()
}

//default implementation
extension Bark {
func bark() { print("Bark") }
}

class Dog: Bark {}

//By calling bark func in Poodle, you change the default implementation.
class Poodle: Dog {
func bark() { print("Yap") }
}

class GermanShephard: Dog {
func bark() { print("Woof") }
}

let dog = Dog()
let poodle = Poodle()
let germanShephard = GermanShephard()

dog.bark()
//Bark
poodle.bark()
//Yap
germanShephard.bark()
//Woof

你也可以不做任何默认实现,只为每种情况添加你自己的实现

评论后编辑:

这是协议(protocol)有用的主要原因之一。它们消除了与子类化相关的紧密耦合。这是一个基本示例,因为整个主题包含很多信息,但您可以创建协议(protocol) DogRepresentable 并分配所有狗实现相同的所有默认属性和功能,而不是将 Dog 子类化。然后你可以扩展 DogRepresentable where self: UIViewController 并实现默认功能:

protocol Barkable {
func bark()
}

protocol DogRepresentable: Barkable {
//properties and functions all dogs will have with same implementation
}

extension DogRepresentable where Self: UIViewController {
//default implementation for functions all dogs will use
}

通过将 Barkable 分配给 DogRepresentable,您知道任何符合 DogRepresentable 的类也必须符合 Barkable。

现在,当您将 DogRepresentable 分配给一个类时,它将获得基类将获得的所有默认实现,并且您被迫调用 bark() 函数以正确遵守协议(protocol):

class Dog: DogRepresentable {
func bark() { print("Bark") }
}

class Poodle: DogRepresentable {
func bark() { print("Yap") }
}

class GermanShephard: DogRepresentable {
//Won't conform because it doesn't have bark()
}

通过这种方式,您可以获得与基类一样的所有默认实现,但不会有忘记覆盖父类(super class)函数的问题。

根据第二条评论编辑 2:

在这种情况下,最好的办法是在不遵守 Barkable 的情况下保留 DogRepresentable,然后为不同类型创建协议(protocol):因此,如果您有爱吠叫的狗,您可以制定一个具有吠叫功能和默认实现的协议(protocol) Yappable。然后你可以有另一个协议(protocol) Barkable 有它自己的树皮函数和它自己的默认实现。然后让类符合它们应该符合的协议(protocol)。 Poodle 符合 Yappable,Dog 符合 Barkable。

通过创建这些单独的协议(protocol),您可以将针对每种情况的功能保留在一个地方,并且只使用您需要的任何一个,从而使您的代码更干净、更具可读性和 DRY。

关于swift - 扩展协议(protocol)以实现不同的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41161013/

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