2016-08-20 5 views
4

Je souhaite forcer un type associé à être Self, mais le compilateur n'en possède aucune.
Voici ce que je veux compiler:Swift Self en tant que type associé lié dans le protocole

protocol Protocol { 
    // Error: Inheritance from non-protocol, non-class type 'Self' 
    associatedtype Type: Self 
} 

Vous pourriez demander, pourquoi ne pas simplement utiliser Self au lieu d'un type associé? Tout simplement parce que je ne peux pas: le type associé est hérité d'un protocole parent. Et cela n'a aucun sens de changer cela dans le protocole parent.
est ici quelque chose de semblable à ce que je suis en train de faire:

protocol Factory { 
    associatedtype Type 

    func new() -> Type 
} 

protocol SelfFactory: Factory { 
    associatedtype Type: Self // Same Error 
} 

Edit:
réponse de mat est presque ce que je cherche. Il se comporte comme je le veux à l'exécution, mais n'est pas assez restrictif au moment de la compilation.
Je veux que cela soit impossible:

protocol Factory { 
    associatedtype MyType 
    static func new() -> MyType 
} 

protocol SelfFactory: Factory { 
    static func new() -> Self 
} 

final class Class: SelfFactory { 

    // Implement SelfFactory: 
    static func new() -> Class { 
     return Class() 
    } 

    // But make the Factory implementation diverge: 
    typealias MyType = Int 

    static func new() -> Int { 
     return 0 
    } 
} 

Je voudrais que le typealias en Class pour déclencher une erreur de redéclaration ou similaire.

+0

Le message d'erreur est absolument correct. La source du problème est indiquée dans vos mots: "le type associé est hérité d'un protocole parent". Non ce n'est pas. Les protocoles ne font pas d'héritage. Vous ne pouvez pas "remplacer" un protocole par un autre comme vous semblez essayer de le faire. Vous adoptez le protocole ou vous ne le faites pas. – matt

+0

"Je voudrais que les typealias en classe déclenchent une erreur de redéclaration ou similaire" Vous ne pouvez pas empêcher la surcharge! 'f() -> Int' et' f() -> String' peuvent co-exister _always_ dans Swift. Vous demandez que la langue soit une langue différente. Vous n'êtes pas le compilateur. - En d'autres termes, l'adoption d'un protocole ne m'empêche pas d'implémenter d'autres méthodes non requises par le protocole! – matt

+0

On ne sait pas ce que vous voulez et pourquoi. Qu'est-ce qui te satisferait? Peut-être votre meilleur pari est d'avoir deux protocoles _unrelated_, Factory et SelfFactory. Et j'adopte juste un d'entre eux. Cela vous rendrait-il heureux? (Mais bien sûr, même alors, vous ne pouvez pas m'empêcher d'adopter les deux si j'en ai envie.) – matt

Répondre

3

Etes-vous en train d'essayer de le dire?

protocol Factory { 
    associatedtype MyType 
    func new() -> MyType 
} 

protocol SelfFactory: Factory { 
    func new() -> Self 
} 
+0

C'est presque ce que je suis après. J'ai édité la question avec plus de détails. Merci de répondre! – ThinkChaos

+0

Après avoir passé un peu plus de temps à lutter contre cela, je crois que c'est actuellement la meilleure solution. Je voudrais pouvoir dire que l'implémentation de 'Factory' de' SelfFactory' est "finale", mais je suppose que cela n'arrivera pas. Et devoir répéter chaque définition de fonction est ennuyeux, mais bon. – ThinkChaos

+0

En fait, cela fonctionne toujours si je définis 'SelfFactory' comme un protocole vide, et implémente la méthode' new' dans une extension. – ThinkChaos

2

Je sais que c'est une vieille question, mais vous pouvez le faire à partir de Swift 4.0:

protocol Factory { 
    associatedtype MyType 
    static func new() -> MyType 
} 

protocol SelfFactory: Factory where MyType == Self { } 

sont pas là où les clauses grande?