Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 调用Swift协议初始值设定项_Ios_Swift_Types_Static_Swift Protocols - Fatal编程技术网

Ios 调用Swift协议初始值设定项

Ios 调用Swift协议初始值设定项,ios,swift,types,static,swift-protocols,Ios,Swift,Types,Static,Swift Protocols,Swift 5,在XCode 11.2.1上。我一直在用Java编程,目前对Swift的熟练程度还不算高,所以我对Java习语的一些理解是有色彩的 假设我们提供了一个协议,或者可能是一个伪抽象类,它可以在单独的模块中实现。然后,程序员将对他们的类的引用传递回第一个模块中的代码,该模块实例化了他们的类。现在,在Java中,这很困难,因为您无法保证子类将定义什么样的初始值设定项/静态方法。但是,在Swift中,您可以。这很整洁。除了,我还没有找到使用它们的方法。我所期望的是,你可以有这样的代码 pr

Swift 5,在XCode 11.2.1上。我一直在用Java编程,目前对Swift的熟练程度还不算高,所以我对Java习语的一些理解是有色彩的

假设我们提供了一个协议,或者可能是一个伪抽象类,它可以在单独的模块中实现。然后,程序员将对他们的类的引用传递回第一个模块中的代码,该模块实例化了他们的类。现在,在Java中,这很困难,因为您无法保证子类将定义什么样的初始值设定项/静态方法。但是,在Swift中,您可以。这很整洁。除了,我还没有找到使用它们的方法。我所期望的是,你可以有这样的代码

protocol FooP {
  init(s: String)
}

func instantiate(clazz: FooP.Type) -> FooP {
  return clazz.init(s: "qwerty")
}
…哦,哦,rrrrr,这确实有效,正如我所希望的那样。我想在我的测试中,我没能找到CLASS/.Type/.self的正确组合来提示我成功的可能性


由于我没有找到关于这种可能性的任何其他信息,尽管搜索了30-60分钟,我还是会回答我自己的问题。

事实证明,您可以使用协议给出的静态方法,即使所涉及的类(不是其实例化)被强制转换为它们的协议。您甚至可以使用泛型使示例
实例化
方法更方便地具有给定类型的返回类型,尽管这会导致如下所示的不同问题。下面是一组代码,演示了您可以做和不能做的事情:

public protocol ProtocolTest {
    init(s: String)

    static func factory(s: String) -> Self
}

public class Foo : ProtocolTest, CustomStringConvertible {
    public let s: String

    public required init(s: String) {
        self.s = s
    }

    public class func factory(s: String) -> Self {
        return Self(s: s)
    }

    public var description: String { return "{\(Self.self)|s:\"\(s)\"}" }
}

public class Bar : Foo {
}

public func instantiateGeneric<T : ProtocolTest>(clazz: T.Type) -> T {
    return clazz.init(s: "qwertyGeneric")
}

public func instantiateNongeneric(clazz: ProtocolTest.Type) -> ProtocolTest {
    return clazz.init(s: "qwertyNongeneric")
}

public func run() {
    let ptts: [ProtocolTest.Type] = [Foo.self, Bar.self]

    // Success
    let aInit : Bar = Bar.init(s: "qwertyInit")
    // Success
    let aGeneric : Bar = instantiateGeneric(clazz: Bar.self)
    // Compile error: Cannot convert value of type 'ProtocolTest' to specified type 'Bar'
    let aNongeneric : Bar = instantiateNongeneric(clazz: Bar.self)

    for ptt in ptts {
        // Success
        let bInit : ProtocolTest = ptt.init(s: "qwertyInit")
        // Compile error: Protocol type 'ProtocolTest' cannot conform to 'ProtocolTest' because only concrete types can conform to protocols
        let bGeneric1 : ProtocolTest = instantiateGeneric(clazz: ptt)
        // Compile error: Cannot invoke 'instantiateGeneric' with an argument list of type '(clazz: ProtocolTest.Type)'
        let bGeneric2 = instantiateGeneric(clazz: ptt)
        // Success
        let bNongeneric : ProtocolTest = instantiateNongeneric(clazz: ptt)
        // This works too, btw:
        let bFactory : ProtocolTest = ptt.factory(s: "qwertyFactory")
    }
}
公共协议协议测试{
init(s:String)
静态函数工厂(s:String)->Self
}
公共类Foo:ProtocolTest,CustomStringConvertible{
公共let s:String
公共必需的init(s:String){
self.s=s
}
公共类函数工厂(s:String)->Self{
返回自我(s:s)
}
公共变量描述:字符串{return“{\(Self.Self){s:\”\(s)\“}”
}
公共类酒吧:富{
}
公共函数实例化eneric(clazz:T.Type)->T{
返回clazz.init(s:“qwertyGeneric”)
}
public func instantiateNongeric(clazz:ProtocolTest.Type)->ProtocolTest{
返回clazz.init(s:“qwertyNongeneric”)
}
公共职能运行(){
让ptts:[ProtocolTest.Type]=[Foo.self,Bar.self]
//成功
让aInit:Bar=Bar.init(s:qwertyInit)
//成功
让aGeneric:Bar=instantialegeneric(clazz:Bar.self)
//编译错误:无法将“ProtocolTest”类型的值转换为指定的“Bar”类型
让aNongeneric:Bar=实例化aNongeneric(clazz:Bar.self)
用于ptt中的ptt{
//成功
让bInit:ProtocolTest=ptt.init(s:“qwertyInit”)
//编译错误:协议类型“ProtocolTest”无法符合“ProtocolTest”,因为只有具体类型才能符合协议
让bGeneric1:ProtocolTest=instantiateGeneric(clazz:ptt)
//编译错误:无法使用类型为“(clazz:ProtocolTest.type)”的参数列表调用“InstanceGeneric”
设bGeneric2=instantialegeneric(clazz:ptt)
//成功
让bNongeneric:ProtocolTest=实例化nongeneneric(clazz:ptt)
//这也行,顺便说一下:
让bFactory:ProtocolTest=ptt.factory(s:“qwertyFactory”)
}
}

我不确定循环中的
instantialegeneric
到底是怎么回事。这似乎是一个合理的代码行。如果你有什么解释,请告诉我。也许关于
协议测试
在技术上不符合
协议测试
,或者它必须是一个严格的子类?不确定。这将是很好的,能够使用相同的方法为两种用途,但我很高兴我能做的,已经。这个发现可能足以让我真正喜欢上斯威夫特,哈哈。

有趣的事实:在一个类中,
static func
相当于
final class func
。另外有趣的事实:似乎当你试图对你的类型产生兴趣的时候,斯威夫特马上就开始攻击你了。例如,显然,如果不指定类型参数,就不能使用泛型类。而且没有任何通配符。