1

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

// 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()

出现一个新错误:

Protocol 'ElementGenerator' can only be used as a generic constraint because it has Self or associated type requirements
4

2 回答 2

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");
    }
}
于 2015-08-31T07:58:51.787 回答
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
于 2015-08-31T08:49:52.393 回答