在Swift中指定协议之间的关系

时间:2015-08-31 07:22:38

标签: swift swift-protocols

我想指定一个管理符合其他协议的某些类型对象的协议。像这样:

Line

尝试编译时,我收到错误:

// Specify protocol
protocol ElementGenerator {
    func getElements() -> [Element]
}
protocol Element {
    // ...
}

// Implement
class FooElementGenerator: ElementGenerator {
    func getElements() -> [FooElement] {
        // Generate elements here
        return [FooElement()]
    }
}
class FooElement {
    // ...
}

暗示候选人Type 'FooElementGenerator' does not conform to protocol 'ElementGenerator' 具有不匹配类型的func getElements() -> [FooElement],而是期望() -> [FooElement]

如何解决这种错误?

更新

这个解决方案似乎有效:

() -> [Element]

但是当我尝试创建这样的变量时:

protocol ElementGenerator {
    typealias T:Element

    func getElements() -> [T]
}

protocol Element {
    // ...
}


class FooElementGenerator: ElementGenerator {
    typealias T = FooElement

    func getElements() -> [T] {
        return [T()]
    }
}

class FooElement: Element {
    // ...
}

出现新错误:

let a: ElementGenerator = FooElementGenerator()

2 个答案:

答案 0 :(得分:1)

实现协议方法时,返回类型必须相同,但您可以像这样返回子类对象;

protocol ElementGenerator {
    func getElements() -> [Element]
}

//@objc for bridging in objective C
@objc protocol Element {
    // ...
}

// Implement
class FooElementGenerator: NSObject,ElementGenerator {

    override init() {
        super.init();
        //--
        let fooElements:[FooElement] = self.getElements() as! [FooElement]
    }

    func getElements() -> [Element] {
        // Generate elements here
        return [FooElement()]
    }
}

class FooElement:NSObject, Element {
    // ...
    override init() {
        super.init();
        //--
        NSLog("FooElement init");
    }
}

答案 1 :(得分:0)

由于您已使用“关联类型”定义ElementGenerator,因此给出了第二种情况中的错误消息,这意味着您只能在为类型提供约束时使用它。

例如,如果您需要为通用ElementGenerator值定义函数,可以编写如下内容:

func f<T1:ElementGenerator>(elemGenerator:T1) -> Element {
  return elemGenerator.getElements()[0]
}

var a : Element = FooElementGenerator()
var b : Element = BarElementGenerator()

var x : Element = f(a)
var y : Element = f(b)

var z : FooElement = f(a) as! FooElement