2015-08-31 3 views
1

Я хочу указать протокол, который управляет объектами определенного типа, которые соответствуют другому протоколу. Как это:Укажите связь между протоколами в Swift

// 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].

Как можно устранить эту ошибку?

UPDATE:

Это решение, кажется, работает:

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 

ответ

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"); 
    } 
} 
+0

Испытано на скор 1,2 – Shoaib

+0

Да, это решение. Наверное, я думал о слишком сложной вещи, поэтому я пропустил эту простую идею. – ULazdins

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 

 Смежные вопросы

  • Нет связанных вопросов^_^