Swift 在泛型和协议(protocol)中使用 Self(在方法级别没有初始化)

标签 swift generics

更新: 该问题投票决定将此作为与 self.init() 的重复交易关闭,这可以通过将类标记为 final 或需要 init 来解决。但是这如何在存储库上工作或从 init 以外的任何其他方法返回(我的实现是 @NSManaged 对象)

这是我想做的。通过请求获取 JSON,然后将其解析为对象。

var req = Request("http://somewhere/story/get/1")
var story = req.parseJsonResponse() as Story

Request 类看起来像这样:

class Request {

    public var httpJsonResponse : String

    init(_ url : String) {
        //This comes from HTTP
        httpJsonResponse = "{}"
    }

    public func parseJsonResponse<T : IParse>() -> T {

        return T.parse(json: httpJsonResponse)

    }

}

现在,我想确保 IParse 实现有解析方法:

protocol IParse {
    static func parse(json : String) -> Self
}

到目前为止一切顺利,这是实现方面的问题:

class Story : IParse {
    required init() 
    {
    }
    public static func parse(json: String) -> Self
    {
        //return self.init() works thanks to @tomahh
        return StoryRepo.ById(1)
    }

}

class StoryRepo {
    public static func ById(_ id : Int) -> Story {
        return Story()
    }
}

这是行不通的。这些都不起作用:

  1. 回归故事
  2. Story() 转换为!自己

查看更新的 Playground gist .

最佳答案

class Story : IParse {
    required init() 
    {
    }

    public static func parse(json: String) -> Self
    {
        return self.init()
    }
}

这会起作用。这确保您实际构建了一个 Self 的实例,这样 StoryTale 子类就不会创建一个无聊的 Story,但确实是一个美妙的故事。

required 关键字强制子类覆盖此 init,因此我们确信在解析中实际调用 self.init() 是有效的。


另一个解决方案,如果你不想与继承斗争,那就是让 Storyfinal

final Story: IParse {
  public static func parse(json: String) -> Story {
    return Story()
  }
}

在这个例子中,因为 Story 永远不会被继承,所以调用 Story() 并返回一个 Story 类型是安全的parse 函数。

关于Swift 在泛型和协议(protocol)中使用 Self(在方法级别没有初始化),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42498699/

相关文章:

c# - 如何对通用列表进行排序?

iOS 9 App Search sendUserActivityToServer 在它失效后,所以什么都不做

swift - 从属性的原始值获取枚举

swift - 在树莓派上运行 Swift

swift - 找不到接受提供的参数的 '/' 的重载

java - 如何获取参数化类型的类引用

当通过参数传递泛型类型时,Swift 无法推断泛型类型

java - 数组的通用列表

ios - 广场 API + OAuth : How do I sign out of my iPad app?

c# - 参数 'T' 与类型参数同名