本文介绍了不支持使用某些协议作为符合另一个协议的具体类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将泛型与协议混合使用,但我遇到了非常困难的时间 xD

我在 Android/Java 项目中实现了某些架构,我正在尝试重写它以适应 swift/iOS 项目.但我发现了这个限制.

协议A

protocol ProtocolA {}

协议B

protocol ProtocolB : ProtocolA {}

实施协议A

class ImplementProtocolA 

{让当前协议:P初始化(当前协议:P){self.currentProtocol = currentProtocol}}

实施协议B

classImplementProtocolB:ImplementProtocolA{}

因此,当我尝试将 ProtocolB 设置为实现 ProtocolA 的具体类型时,我收到此错误:

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

1 这种限制"有什么原因吗?

2 是否有任何解决方法来实现这一点?

3 它会在某个时候得到支持吗?

--更新--

我认为是同一问题的另一种变体:

查看协议

协议查看{}协议 GetUserView :查看 {func showProgress()函数隐藏进度()功能显示错误(消息:字符串)func showUser(userDemo:UserDemo)}

演示者协议

protocol Presenter {typealias V : 查看}类 UserDemoPresenter :演示者 {类型别名 V = GetUserView}

错误:

UserDemoPresenter.swift 可能打算匹配 'V'(又名'GetUserView') 不符合 'View'

那是什么??符合!

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

class UserDemoPresenter : Presenter {类型别名 V = 视图}

UserDemoPresenter.swift 可能打算匹配 'V'(又名 'View')不符合视图"

xxDD 我真的不明白.

--更新--

Rob Napier 提出的解决方案并没有解决问题,而是延迟了.

当尝试定义对 UserDemoPresenter 的引用时,我需要指定泛型类型,因此出现相同的错误:

私有变量演示者:UserDemoPresenter

使用'GetUserView'作为符合协议的具体类型不支持GetUserView"

解决方案

限制的根本原因是 Swift 没有一流的元类型.最简单的例子是这不起作用:

func isEmpty(xs: Array) ->布尔{返回 xs.count == 0}

理论上,这段代码可以工作,如果可以的话,我可以制作很多其他类型(比如 Functor 和 Monad,今天真的无法在 Swift 中表达).但你不能.您需要帮助 Swift 将其确定为具体类型.我们经常用泛型来做到这一点:

func isEmpty(xs: [T]) ->布尔{返回 xs.count == 0}

注意 T 在这里是完全多余的.我没有理由必须表达它;它从未使用过.但是 Swift 需要它,所以它可以将抽象的 Array 变成具体的 [T].您的情况也是如此.

这是一个具体类型(好吧,它是一个抽象类型,在实例化和填充 P 时将变成具体类型):

classImplementProtocolA

这是一个完全抽象的类型,Swift 没有任何规则可以将其转换为具体类型:

classImplementProtocolB :ImplementProtocolA

你需要把它具体化.这将编译:

classImplementProtocolB:ImplementProtocolA<T>{}

还有:

class UserDemoPresenter: 主持人 {类型别名 V = T}

仅仅因为您以后可能会遇到这个问题:如果您制作这些结构体或final 类,您的生活会变得更轻松.混合协议、泛型和类多态性充满了非常锋利的边缘.有时你很幸运,它只是不会编译.有时它会调用你意想不到的东西.

您可能对对 AnySequence 的一点尊重感兴趣,其中详细介绍了一些相关问题.

私有变量演示者:UserDemoPresenter

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

final class something{私有变量演示者:UserDemoPresenter}

如果这造成了问题,您需要创建一个框.请参阅协议不符合自身? 以讨论如何键入擦除你可以持有抽象类型.但是您需要在具体类型中工作.你不能最终专注于一个协议.在大多数情况下,您最终必须专注于具体的事情.

I’m trying to mix generics with protocols and I’m getting a really hard time xD

I have certain architecture implemented in an Android/Java project, and I’m trying to rewrite it to fit it in a swift/iOS project. But I’ve found this limitation.

ProtocolA

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> {

}

So, when I try to set ProtocolB as the concrete type that implements ProtocolA, I get this error:

Using 'ProtocolB' as a concrete type conforming to protocol 'ProtocolA' is not supported

1 Is there any reason for this "limitation"?

2 Is there any workaround to get this implemented?

3 Will it be supported at some point?

--UPDATED--

Another variant of the same problem, I think:

View protocols

protocol View {

}

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

Presenter protocols

protocol Presenter {
    typealias V : View
}

class UserDemoPresenter : Presenter {
    typealias V = GetUserView
}

Error:

What is that?? It conforms!

Even if I use View instead of GetUserView, it does not compile.

class UserDemoPresenter : Presenter {
    typealias V = View
}

xxDD I don’t get it, really.

--UPDATED--

With the solution proposed by Rob Napier the problem is not fixed, instead, it is just delayed.

When a try to define a reference to UserDemoPresenter, I need to specify the generic type, so I get the same error:

private var presenter : UserDemoPresenter<GetUserView>
解决方案

The underlying reason for the limitation is that Swift doesn't have first-class metatypes. The simplest example is that this doesn't work:

func isEmpty(xs: Array) -> Bool {
    return xs.count == 0
}

In theory, this code could work, and if it did there would be a lot of other types I could make (like Functor and Monad, which really can't be expressed in Swift today). But you can't. You need to help Swift nail this down to a concrete type. Often we do that with generics:

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

Notice that T is totally redundant here. There is no reason I should have to express it; it's never used. But Swift requires it so it can turn the abstract Array into the concrete [T]. The same is true in your case.

This is a concrete type (well, it's an abstract type that will be turned into a concrete type any time it's instantiated and P is filled in):

class ImplementProtocolA<P : ProtocolA>

This is a fully abstract type that Swift doesn't have any rule to turn into a concrete type:

class ImplementProtocolB : ImplementProtocolA<ProtocolB>

You need to make it concrete. This will compile:

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

And also:

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

Just because you're likely to run into the issue later: your life will go much easier if you'll make these structs or final classes. Mixing protocols, generics, and class polymorphism is full of very sharp edges. Sometimes you're lucky and it just won't compile. Sometimes it will call things you don't expect.

You may be interested in A Little Respect for AnySequence which details some related issues.


private var presenter : UserDemoPresenter<GetUserView>

This is still an abstract type. You mean:

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

If that creates a problem, you'll need to create a box. See Protocol doesn't conform to itself? for discussion of how you type-erase so that you can hold abstract types. But you need to work in concrete types. You can't ultimately specialize on a protocol. You must eventually specialize on something concrete in the majority of cases.

这篇关于不支持使用某些协议作为符合另一个协议的具体类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 04:03