Swift 使用符合协议的类作为参数创建类的新实例

Swift 使用符合协议的类作为参数创建类的新实例,swift,generics,instantiation,swift-protocols,Swift,Generics,Instantiation,Swift Protocols,我有以下代码设置(用Swift编写): 协议数据获取类型{ init(uu-mainData:String,fetchData:Bool) } 类DataFetcher1:DataFetcherType{ 必需的初始化(uMainData:String,fetchData:Bool){ } } 类DataFetcher2:DataFetcherType{ 必需的初始化(uMainData:String,fetchData:Bool){ } } 结构数据{ var主数据:字符串 变量获取程序:Da

我有以下代码设置(用Swift编写):

协议数据获取类型{
init(uu-mainData:String,fetchData:Bool)
}
类DataFetcher1:DataFetcherType{
必需的初始化(uMainData:String,fetchData:Bool){
}
}
类DataFetcher2:DataFetcherType{
必需的初始化(uMainData:String,fetchData:Bool){
}
}
结构数据{
var主数据:字符串
变量获取程序:DataFetcherType
init(uMainData:String,使用fetcher:FetcherType,fetchData:Bool=true){
self.mainData=mainData
self.fetcher=FetcherType(mainData,fetchData:fetchData)
}
}
我试图实例化
数据
,如下所示:

数据(“foo”,使用:DataFetcher1)
但我得到了一个错误:

类型“DataFetcher1.Type”不能与“DataFetcherType”一致

如果我尝试使用
DataFetcher2
,情况也是如此


我已经做了几个小时了,我觉得我已经改变了所有可能的事情,但我就是无法让它发挥作用。我最初的尝试没有使用泛型,但我最终决定这可能是我需要做的。这是错误的,还是我基本上忽略了Swift的工作原理?

通过参数,必须采用类型而不是对象

将数据结构初始值设定项重写为:

struct数据{
var主数据:字符串
变量获取程序:DataFetcherType
init(uMainData:String,使用fetcher:FetcherType.Type,fetchData:Bool=true){
self.mainData=mainData
self.fetcher=FetcherType(mainData,fetchData:fetchData)
}
}
让data=data(“datafetcher1”,使用:DataFetcher2.self)
打印(data.fetcher)

您根本不需要传递任何类型。使用参数的
是完全不必要的。删除它。这是一个泛型;传递类型会使泛型变得毫无意义

声明要实例化的内容时,只需解析泛型。(不要称某个东西为数据,该名称已被采用。)

因此,如果我们从这个开始:

protocol DataFetcherType {
    init(_ mainData: String, fetchData: Bool)
}
class DataFetcher1: DataFetcherType {
    required init(_ mainData: String, fetchData: Bool) {
    }
}
class DataFetcher2: DataFetcherType {
    required init(_ mainData: String, fetchData: Bool) {
    }
}
。。。这就是你所需要的:

struct MyData<FetcherType: DataFetcherType> {
    var mainData: String
    var fetcher: FetcherType
    init(_ mainData: String, fetchData: Bool = true) {
        self.mainData = mainData
        self.fetcher = FetcherType.init(mainData, fetchData: fetchData)
    }
}
struct MyData{
var主数据:字符串
变量获取程序:获取类型
init(umaindata:String,fetchData:Bool=true){
self.mainData=mainData
self.fetcher=FetcherType.init(maindat,fetchData:fetchData)
}
}
…因为要创建一个,您只需解析类型:

    let mydata = MyData<DataFetcher1>("hey")
让mydata=mydata(“嘿”)
另外,请注意,我已经更改了变量
fetcher
的类型。它应该是泛型类型,而不是协议

一般来说,如果你发现自己在Swift中传递类型,那是一种难闻的气味,你应该重新思考。这是可以做到的,有时也是可以做到的,但总的来说Swift不喜欢元类型,你应该避免它们

协议也是如此;如果您发现您正在键入协议,请重新考虑


这正是泛型存在的原因,所以您不需要执行这些操作。

在您的数据结构初始值设定项中,执行self.fetcher=fetcher,这正是您想要实现的目标?@Kazi否,因为我仍然需要使用
mainData
和其他参数初始化fetcher。目标是实例化
数据
并让它自动/异步获取相关数据很抱歉,这是不正确的。您不需要传递类型,这样做使泛型完全没有意义。而且将变量作为协议键入也是错误的。@matt您完全正确,但我仅尝试解决他的错误,是的,根据他的实现,当他可以通过初始值设定项获取类型时,没有理由使用泛型。但我不明白为什么键入一个变量作为协议是错误的?嘿,非常感谢。这很有道理,你完美地回答了我的问题。但我意识到我没有传达我想要的细节。我希望在创建
MyData
实例时不要使用通用语法,如果可能的话,最好将枚举之类的东西作为参数传递,这样调用将是
let MyData=MyData(“嘿”,使用:.DataFetcher1)
。我知道您的解决方案实现了相同的目标,但我试图使调用语法尽可能优雅/可读,即使这可能被认为是一种不好的做法。想法?没有足够的信息。你为什么要这么做?任何时候你发现自己在切换这样的类型,这听起来像是最糟糕的OOP。