如何从Swift协议返回“[Self]”?

时间:2016-01-22 09:10:52

标签: swift self swift-protocols

我的协议实现如下。

protocol DatabaseInjectable {

    static func deriveObjectFromDBRow(row: [String]) -> Self? // Method - 1

    static func collectAllObjectsForDatabaseAction(action: (Database) -> Void) -> [Self]? // Method - 2
}

我成功通过Method - 1这样的代理实施:

static func deriveObjectFromDBRow(row: [String]) -> Self? {

    ...
}

但是我无法像这样实现Method - 2

static func collectAllObjectsForDatabaseAction(action: (WWDatabase) -> Void) -> [Self]? {

    ...
}

我收到这样的错误:

'Self' is only available in a protocol or as the result of a method in a class;

任何帮助返回数组形式的 Self(自己的类)都会很好。

3 个答案:

答案 0 :(得分:1)

如果您可以设置班级final,则可以使用班级名称替换Self

final class SampleClass: DatabaseInjectable {
    init() {
    }
    static func deriveObjectFromDBRow(row: [String]) -> SampleClass? {
        return SampleClass()
    }

    static func collectAllObjectsForDatabaseAction(action: (Database) -> Void) -> [SampleClass]? {
        let array = [SampleClass]()
        return array
    }
}

答案 1 :(得分:0)

这是一个写得很好的答案here,但简而言之,您可以将协议定义为:


protocol DatabaseInjectable {

    static func deriveObjectFromDBRow(row: [String]) -> DatabaseInjectable? // Method - 1

    static func collectAllObjectsForDatabaseAction(action: (Database) -> Void) -> [DatabaseInjectable]? // Method - 2
}

答案 2 :(得分:0)

您可以在协议typealias中使用DatabaseInjectable,并在符合协议的类中将其用作Self类别的别名。

class Database {
    var desc : String = "Default"
}

protocol DatabaseInjectable {
    typealias MySelf

    static func deriveObjectFromDBRow(row: [String]) -> MySelf?

    static func collectAllObjectsForDatabaseAction(action: (Database) -> Void) -> [MySelf]?
}

class MyClass : DatabaseInjectable {
    typealias MySelf = MyClass

    static func deriveObjectFromDBRow(row: [String]) -> MySelf? {
        return MyClass()
    }

    static func collectAllObjectsForDatabaseAction(action: (Database) -> Void) -> [MySelf]? {
        return [MyClass(), MyClass()]
    }
}

/* example */
let closure : (Database) -> () = { print($0.desc) }
var arr : [MyClass]? = MyClass.collectAllObjectsForDatabaseAction(closure)
/* [MyClass, MyClass] */

然而,这里的一个缺点是你可以设置例如typealias MySelf = Int(在类中)并让你的函数返回一个整数/整数数组(而不是self / [Self]),并且仍然符合你的协议。可能这是一个交易破坏者。