【问题标题】:How to type generic protocol to be able to use them as return type [duplicate]如何键入通用协议以便能够将它们用作返回类型[重复]
【发布时间】:2018-12-28 10:02:15
【问题描述】:

以下代码不起作用。 我来自 Java 世界,我不明白为什么只要指定 typealias 就不能返回泛型协议?

我尝试在 UserDao 中使用associatedType Element: Usertypealias Element = User 对其进行专门化,但每次 getTest() 方法都返回相同的错误:

Protocol 'UserDao' can only be used as a generic constraint because it has Self or associated type requirements

swift 有什么好方法?

import Foundation

protocol HasId {
}

protocol BaseDao {
    associatedtype Element: HasId
}

protocol UserDao: BaseDao {
    // already tried these solutions...
    // associatedType Element: User
    // typealias Element = User
}

class User: HasId {}

class Test {
    func getTest() -> UserDao? { // Error is on the return type
        return nil
    }
}

【问题讨论】:

标签: swift generics protocols


【解决方案1】:
error: protocol 'UserDao' can only be used as a generic constraint because it has Self or associated type requirements

编译器给你上面的错误。

您不能将具有关联类型的协议用作函数参数或返回类型,因为它需要知道与协议关联的类型别名。

如果您来自 Java 世界,这似乎令人沮丧,但解决方案是使用一个类来定义与您的类型关联的类型别名。

protocol BaseDao {
    associatedtype Element: HasId
}

class UserDao: BaseDao {
    typealias Element = User
}

You can see a more complete answer here.

【讨论】:

  • 这会起作用,但我想创建不同的 UserDao 实现:MemoryUserDao、FirebaseUserDao、....所以每个都实现了 UserDao 协议。但正如 Preskhya 指出的那样,没有办法迅速轻松地实现这一目标。还是谢谢!
  • @Spoke44 如果这是一个新项目,您应该检查一下您的 dao 架构。这种系统我写过很多次,也许你可以只有一个 Dao 对象类型(每个表一个),但给了它执行保存的方法。就像具有“MemoryDataProxy”、“FirebaseDataProxy”等实现的协议“DataProxy”,您将其发送到 BaseDao(作为简单协议 DataProxy),然后只需调用 DataProxy.save() 或 fetch()。而且您的代理只是具有通用实现而不是特定于表,因此可以由 dao 对象提供。祝你好运!
【解决方案2】:

UserDao 更改为classstruct

class UserDao: BaseDao {
    typealias Element = User
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-09
    • 2020-06-04
    • 2020-11-22
    • 2021-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多