【问题标题】:return protocol with associated type返回具有关联类型的协议
【发布时间】:2019-08-09 10:09:43
【问题描述】:

如何返回关联类型的协议?

protocol AProtocol {

}

class A: AProtocol {

}

class Main {
    func sendA() -> AProtocol {
        return A()
    }
}

它有效。

但是

protocol BProtocol {
    associatedtype B
}

class B: BProtocol {
    typealias B = Int
}

class Main {
    func sendA() -> AProtocol {
        return A()
    }

    func sendB() -> BProtocol { // error
        return B()
    }

// function1
    func sendB_<T: BProtocol>() -> T{
        return B() as! T
    }
}

我想在函数 1 中返回 'return B()' 有可能吗?

【问题讨论】:

  • 改成返回B?

标签: ios swift generics protocols


【解决方案1】:

您正试图在案例 1 中返回 BProtocol。问题是 PAT(具有关联类型的协议)是不完全是类型。它们充当类型的占位符。所以你不能直接返回BProtocol

斯威夫特 5.1

我不是 100% 确定,但我认为在 swift (5.1) 的下一次迭代中,他们引入了不透明类型,可以实现您想要的功能。

在这种情况下,您可以这样称呼它:

func sendB() -> some BProtocol { 
    return B()
}

【讨论】:

    【解决方案2】:

    在这个函数中

    func sendB_<T: BProtocol>() -> T{
        return B() as! T
    }
    

    您不能将B 作为T 返回,因为使用该函数的人定义了T,而不是您,而T 可以是符合Protocol 的任何类型例如,我可以这样做:

    class C: BProtocol 
    {
        typealias B = Float
    }
    
    let c: C = Main().sendB_()
    

    通过这样做,我将T 设置为CsendB_() 中的强制类型转换将失败。

    不幸的是,具有关联类型的协议本身不能被视为具体类型,因此您使用 AProtocol 采用的方法将不起作用。

    在我看来,您有两个选择。将您的函数返回类型更改为B。毕竟,你总是返回一个B

    func sendB_() -> B {
        return B()
    }
    

    如果您想保持通用,请尝试

    protocol BProtocol 
    {
        associatedtype B
    
        init() // Needed to be able to do T() in generic function
    }
    
    func sendB_<T: BProtocol>() -> T{
        return T()
    }
    

    您需要将初始化程序添加到协议中,以确保始终存在 T 类型的实例。

    【讨论】:

      猜你喜欢
      • 2022-11-27
      • 1970-01-01
      • 2021-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多