-1

我正在尝试将我的设计转换为pop. 但是,我被卡住了,并且我的方法已经有了一堆线程-尽管不是这个问题的重复-显然它们都是死胡同。

我的问题是,有没有办法覆盖从另一个协议继承的协议方法的参数类型?

struct Books: Codable {}

protocol Listener {
    func listen(_ param: Codable)
}

protocol BooksListener: Listener {
    func listen(_ param: Books)
}


class MyClass: BooksListener {
    // I want only this one to required with the type.
    func listen(_ param: Books) {
        <#code#>
    }
    
    func listen(_ param: Codable) {
        <#code#>
    }
}

我做了我的研究,我相信这不是协议的工作方式。我只是在寻找解决方案。

我尝试添加 aassociatedType并将Listener其用作里面的类型listen(_:)。但是这个解决方案限制任何类必须符合多个从Listener. 详细信息可以在这里找到

4

1 回答 1

1

作为一般规则,Swift 协议不是协变的。但是您的问题是一种特殊情况,即使 Swift 允许协议协方差,您的方法也行不通。

在您的示例中,BooksListener 需要执行 Listener 可以执行的所有操作。Listener 可以将任意 Codable 作为其参数listen。这意味着 BooksListener必须能够接受任意 Codable。考虑以下:

struct Books: Codable {}

protocol Listener {
    func listen(_ param: Codable)
}

protocol BooksListener: Listener {
    func listen(_ param: Books)
}

class MyClass: BooksListener {
    // Illegal, but assuming you had what you're asking for
    func listen(_ param: Books) {}
}

let l: Listener = MyClass()
l.listen("Strings are Codable, and Listener accepts Codable")

这会做什么?这违反了LSP

您在这里可能想要的是您提到的关联类型(但我稍后会解释为什么您可能不这样做)。使用关联类型,您可以按照我期望的方式定义 Listener。

struct Books: Codable {}

protocol Listener {
    associatedtype Parameter: Codable
    func listen(_ param: Parameter)
}

protocol BooksListener: Listener where Parameter == Books {
    func listen(_ param: Books)
}

class MyClass: BooksListener {
    func listen(_ param: Books) {}
}

你为什么不想要这个?因为它几乎肯定没有任何意义。我可以用任意的 Listener 做什么?我无法调用listen它;我不知道参数的类型。没有任何算法可以提供帮助。启用算法是关联类型的意义所在。

但真正的重点是“POP”并不意味着“使用大量协议”,也绝对不意味着“使用协议重新创建类继承”。这意味着“从具体类型开始,提取协议以共享算法”。所以在你创建一个单一的协议之前,你需要问,你的程序中还有哪些其他类型的监听器,以及在任意监听器上需要什么算法?如果没有这样的算法,就不应该有协议。

于 2021-02-16T14:43:21.683 回答