加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

swift – 不支持使用一些协议作为符合另一个协议的具体类型

发布时间:2020-12-14 05:58:23 所属栏目:百科 来源:网络整理
导读:我正在尝试将泛型与协议混合起来,而且我真的很难xD 我在Android / Java项目中实现了一定的架构,我正在尝试重写它以适应一个swift / iOS项目。但是我发现了这个限制。 协议A. protocol ProtocolA {} ProtocolB protocol ProtocolB : ProtocolA {} Implement
我正在尝试将泛型与协议混合起来,而且我真的很难xD

我在Android / Java项目中实现了一定的架构,我正在尝试重写它以适应一个swift / iOS项目。但是我发现了这个限制。

协议A.

protocol ProtocolA {

}

ProtocolB

protocol ProtocolB : ProtocolA {

}

ImplementProtocolA

class ImplementProtocolA <P : ProtocolA> {

    let currentProtocol : P

    init(currentProtocol : P) {
        self.currentProtocol = currentProtocol
    }

}

ImplementProtocolB

class ImplementProtocolB : ImplementProtocolA<ProtocolB> {

}

所以,当我尝试将ProtocolB设置为实现ProtocolA的具体类型时,我得到这个错误:

不支持使用“ProtocolB”作为符合协议“ProtocolA”的具体类型

有没有这个“限制”的理由?

2有没有解决方法来实现这一点?

3有什么需要支持吗?

– 更新 –

同样的问题的另一个变体,我想:

查看协议

protocol View {

}

protocol GetUserView : View {
    func showProgress()
    func hideProgress()
    func showError(message:String)
    func showUser(userDemo:UserDemo)
}

演示者协议

protocol Presenter {
    typealias V : View
}

class UserDemoPresenter : Presenter {
    typealias V = GetUserView
}

错误:

UserDemoPresenter.swift Possibly intended match ‘V’ (aka
‘GetUserView’) does not conform to ‘View’

那是什么??它符合!

即使我使用View而不是GetUserView,它也不会编译。

class UserDemoPresenter : Presenter {
    typealias V = View
}

UserDemoPresenter.swift Possibly intended match ‘V’ (aka ‘View’) does
not conform to ‘View’

xxDD我不明白,真的。

– 更新 –

随着Rob Napier提出的解决方案,问题不是固定的,而是延迟。

当尝试定义对UserDemoPresenter的引用时,我需要指定泛型类型,所以我得到相同的错误:

private var presenter : UserDemoPresenter<GetUserView>

Using ‘GetUserView’ as a concrete type conforming to protocol
‘GetUserView’ is not supported

限制的根本原因是Swift没有一流的元类型。最简单的例子是这不行:
func isEmpty(xs: Array) -> Bool {
    return xs.count == 0
}

在理论上,这段代码可以工作,如果这样做会有很多我可以做的其他类型(如Functor和Monad,这在Swift今天不能表达)。但你不能。你需要帮助Swift把它钉在一个具体的类型上。我们通常用泛型:

func isEmpty<T>(xs: [T]) -> Bool {
    return xs.count == 0
}

请注意,T在这里是完全冗余的。没有理由我应该表达它;它从来没有被使用过。但是Swift需要它,所以它可以将抽象数组变成具体的[T]。在你的情况下也是如此。

这是一个具体的类型(嗯,它是一个抽象类型,将被变成一个具体的类型,任何时间实例化和P填充):

class ImplementProtocolA<P : ProtocolA>

这是一个完全抽象的类型,Swift没有任何规则变成具体的类型:

class ImplementProtocolB : ImplementProtocolA<ProtocolB>

你需要具体化。这将编译:

class ImplementProtocolB<T: ProtocolB> : ImplementProtocolA<T> {}

并且:

class UserDemoPresenter<T: GetUserView> : Presenter {
    typealias V = T
}

只是因为你可能会遇到这个问题:如果你做这些结构或最终的课程,你的生活将会变得更加简单。混合协议,泛型和类多态性充满了非常锋利的边缘。有时你很幸运,只是不会编译。有时它会调用你不期望的东西。

您可能对A Little Respect for AnySequence有兴趣了解一些相关问题。

private var presenter : UserDemoPresenter<GetUserView>

这仍然是一个抽象类型。你意思是:

final class Something<T: GetUserView> {
    private var presenter: UserDemoPresenter<T>
}

如果这造成问题,您需要创建一个框。请参阅Protocol doesn’t conform to itself?讨论如何进行类型擦除,以便可以保存抽象类型。但是你需要在具体的类型中工作。你最终不能专门从事协议。在大多数情况下,你必须最终专注于具体的事情。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读