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
在基类中实现Swift协议方法_Swift - Fatal编程技术网

在基类中实现Swift协议方法

在基类中实现Swift协议方法,swift,Swift,我有一个定义如下方法的Swift协议: protocol MyProtocol { class func retrieve(id:String) -> Self? } class MyBaseClass : MyProtocol { class func retrieve<T:MyBaseClass>(id:String, successCallback: (T) -> (), failureCallback: (NSError) -> ())

我有一个定义如下方法的Swift协议:

protocol MyProtocol {

    class func retrieve(id:String) -> Self?
}
class MyBaseClass : MyProtocol {
    class func retrieve<T:MyBaseClass>(id:String, successCallback: (T) -> (), failureCallback: (NSError) -> ()) {
        // Perform retrieve logic and on success invoke successCallback with an object of type `T`
    }
}
class MyClass1 : MyBaseClass {    
    func success(result:MyClass1} {
        ...
    }
    func failure(error:NSError) {
        ...
    }
    class func doSomething {
        MyClass1.retrieve("objectID", successCallback:success, failureCallback:failure)
    }
我有几个不同的类将符合此协议:

class MyClass1 : MyProtocol { ... }
class MyClass2 : MyProtocol { ... }
class MyClass3 : MyProtocol { ... }
class MyBaseClass : MyProtocol
{
    class func retrieve(id:String) -> MyBaseClass?   
}

class MyClass1 : MyBaseClass { ... }
class MyClass2 : MyBaseClass { ... }
class MyClass3 : MyBaseClass { ... }
每个子类中
retrieve
方法的实现几乎相同。我想将这些函数的通用实现拉入符合协议的共享超类:

class MyClass1 : MyProtocol { ... }
class MyClass2 : MyProtocol { ... }
class MyClass3 : MyProtocol { ... }
class MyBaseClass : MyProtocol
{
    class func retrieve(id:String) -> MyBaseClass?   
}

class MyClass1 : MyBaseClass { ... }
class MyClass2 : MyBaseClass { ... }
class MyClass3 : MyBaseClass { ... }
这种方法的问题是,我的协议将
retrieve
方法的返回类型定义为type
Self
,这是我最终真正想要的。但是,因此,我无法以这种方式在基类中实现
检索
,因为它会导致
MyClass1
MyClass2
MyClass3
的编译器错误。这些类中的每一个都必须符合它们从
MyBaseClass
继承的协议。但是,由于该方法是使用返回类型
MyBaseClass
实现的,并且协议要求它必须是
MyClass1
,因此它表示我的类不符合协议

我想知道是否有一种干净的方法可以实现一个协议方法,该方法在基类中的一个或多个方法中引用
Self
类型。当然,我可以在基类中实现一个不同名称的方法,然后让每个子类通过调用其超类的方法来实现协议,但这在我看来并不特别优雅

这里有没有我缺少的更直接的方法?

这应该可以:

protocol MyProtocol {
    class func retrieve(id:String) -> Self?
}

class MyBaseClass: MyProtocol {

    required init() { }

    class func retrieve(id:String) -> Self? {
        return self()
    }
}
required init()


请注意,此代码会导致Swift Playerd崩溃。我不知道为什么。因此,请尝试使用real project。

仅通过您的示例不确定您希望在这里实现什么,因此这里有一个可能的解决方案:

protocol a : class {
  func retrieve(id: String) -> a?
}

class b : a {
  func retrieve(id: String) -> a? {
    return self
  }
}
背后的理由

protocol a : class

声明是这样的,所以只有引用类型可以作为扩展。在处理类时,您可能不希望传递值类型(struct)。

我已将@rintaro的答案标记为正确答案,因为它确实回答了我提出的问题。然而,我发现这个解决方案太有限了,所以我在这里发布了一个备选答案,我发现它适用于任何遇到这个问题的人

前面答案的局限性在于,它仅在协议中使用由
Self
表示的类型(在我的示例中是
MyClass1
MyClass2
,或
MyClass3
)或作为类方法的返回类型时才起作用。所以当我有了这个方法

class func retrieve(id:String) -> Self?
一切都如我所愿。然而,当我完成这项工作时,我意识到这个方法现在需要是异步的,并且不能直接返回结果。所以我用class方法尝试了这一点:

class func retrieve(id:String, successCallback:(Self) -> (), failureCallback:(NSError) -> ())
我可以将此方法放入
MyProtocol
中,但是当我尝试在
MyBaseClass
中实现时,我得到以下编译器错误:

Error:(57, 36) 'Self' is only available in a protocol or as the result of a class method; did you mean 'MyBaseClass'?
因此,除非以非常具体的方式使用
Self
引用的类型,否则我真的不能使用这种方法

经过一些实验和大量的研究,我终于能够使用泛型让一些东西更好地工作。我在协议中定义的方法如下:

class func retrieve(id:String, successCallback:(Self) -> (), failureCallback:(NSError) -> ())
然后在我的基类中,我做了以下工作:

protocol MyProtocol {

    class func retrieve(id:String) -> Self?
}
class MyBaseClass : MyProtocol {
    class func retrieve<T:MyBaseClass>(id:String, successCallback: (T) -> (), failureCallback: (NSError) -> ()) {
        // Perform retrieve logic and on success invoke successCallback with an object of type `T`
    }
}
class MyClass1 : MyBaseClass {    
    func success(result:MyClass1} {
        ...
    }
    func failure(error:NSError) {
        ...
    }
    class func doSomething {
        MyClass1.retrieve("objectID", successCallback:success, failureCallback:failure)
    }

在这个实现中,
success
的函数类型告诉编译器在
MyBaseClass

retrieve
的实现中应该为
T
应用什么类型,我将这个答案标记为正确答案,因为它确实回答了我所问的问题。然而,我发现它不足以满足我的需求,因为我对其他因素没有足够的了解。我将为感兴趣的人发布我自己的答案和详细信息。这并不是我想要的,因为它告诉Swift我正在返回一个实现协议“a”的对象,而不是返回一个类b的实例。此外,它不允许我实现一个名为“c”的“b”子类并让检索方法返回一个“c”实例