Cette déclaration
protocol SomeProtocol : AnyObject {
}
et cette déclaration
protocol SomeProtocol : class {
}
semblent faire en sorte que seules les classes puissent se conformer à ce protocole (c'est-à-dire que les instances du protocole sont des références à des objets), et n'ont pas d'autres effets.
Y a-t-il une différence entre eux? Faut-il préférer l'un à l'autre? Sinon, pourquoi y a-t-il deux façons de faire la même chose?
J'utilise la dernière version de Xcode 6.3.1.
Cela a été répondu par un officiel Swift dev (Slava_Pestov) sur le forums Swift . Voici le résumé:
Vous devez utiliser AnyObject
(protocol SomeProtocol: AnyObject
).
AnyObject
et class
sont équivalents. Il n'y a pas de différence.
class
sera finalement déconseillé.Concernant la réponse https://forums.Swift.org/t/class-only-protocols-class-vs-anyobject/11507/4 , cette réponse est déconseillée. Ces mots sont les mêmes maintenant.
[~ # ~] déconseillé [~ # ~]
Mise à jour: Après avoir consulté les pouvoirs en place , les deux définitions sont supposé pour être équivalentes, AnyObject
étant utilisé comme remplaçant pendant class
était en cours de finition. À l'avenir, ces derniers éviteront les premiers mais, pour l'instant, ils présentent quelques différences mineures.
La différence réside dans la sémantique de @objc
déclarations. Avec AnyObject
, on s'attend à ce que les classes conformes soient ou non des objets Objective-C appropriés, mais le langage les traite quand même comme tels (en ce que vous perdez parfois la répartition statique). La leçon à en tirer est que vous pouvez traiter un AnyObject
et al. contrainte de protocole comme moyen de demander @objc
fonctions membres comme indiqué dans l'exemple dans la documentation de AnyObject
dans la STL:
import Foundation
class C {
@objc func getCValue() -> Int { return 42 }
}
// If x has a method @objc getValue()->Int, call it and
// return the result. Otherwise, return nil.
func getCValue1(x: AnyObject) -> Int? {
if let f: ()->Int = x.getCValue { // <===
return f()
}
return nil
}
// A more idiomatic implementation using "optional chaining"
func getCValue2(x: AnyObject) -> Int? {
return x.getCValue?() // <===
}
// An implementation that assumes the required method is present
func getCValue3(x: AnyObject) -> Int { // <===
return x.getCValue() // x.getCValue is implicitly unwrapped. // <===
}
Le même exemple tombe immédiatement si vous changez cela en un protocole dérivant class
:
import Foundation
protocol SomeClass : class {}
class C : SomeClass {
@objc func getCValue() -> Int { return 42 }
}
// If x has a method @objc getValue()->Int, call it and
// return the result. Otherwise, return nil.
func getCValue1(x: SomeClass) -> Int? {
if let f: ()->Int = x.getCValue { // <=== SomeClass has no member 'getCValue'
return f()
}
return nil
}
// A more idiomatic implementation using "optional chaining"
func getCValue2(x: SomeClass) -> Int? {
return x.getCValue?() // <=== SomeClass has no member 'getCValue'
}
// An implementation that assumes the required method is present
func getCValue3(x: SomeClass) -> Int { // <===
return x.getCValue() // <=== SomeClass has no member 'getCValue'
}
Il semble donc que class
soit une version plus conservatrice de AnyObject
qui devrait être utilisée lorsque vous ne vous souciez que de la sémantique de référence et non des recherches de membres dynamiques ou du pontage Objective-C.
Dans le Guide du langage de programmation Swift pour les protocoles , sous la section Protocoles de classe uniquement . Il ne mentionnait que AnyObject
, mais pas class
.
Vous pouvez limiter l'adoption du protocole aux types de classe (et non aux structures ou énumérations) en ajoutant le protocole AnyObject à la liste d'héritage d'un protocole.
protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
// class-only protocol definition goes here
}
Pour cette raison, je suggérerai d'utiliser AnyObject
sur class
pour un nouveau code ou un nouveau projet. À part ça, je ne vois aucune différence évidente entre eux.
AnyObject
est un protocole auquel toutes les classes sont implicitement conformes ( source ). Je dirais donc qu'il n'y a pas de différence: vous pouvez utiliser l'une ou l'autre pour exiger une contrainte de classe.
Si vous ouvrez l'aide (alt-clic) dans Xcode 9 pour class
sur une ligne telle que protocol P: class {}
, tu auras typealias AnyObject
.
Ainsi, le code compilé (dans Swift 4) sera le même si vous contraignez le protocole à class
ou AnyObject
.
Cela dit, il y a aussi la question de style et options futures - un futur Swift pourrait vouloir traiter class
et AnyObject
différemment de façon subtile, même si ce n'est pas le cas actuellement.
J'ai mal parlé avant. @MartinR devrait vraiment répondre à cette question, car c'est lui qui m'a corrigé et a fourni les informations correctes.
La différence réelle est qu'un protocole avec le qualificatif de classe ne peut être appliqué qu'à une classe, pas une structure ou une énumération.
Martin, pourquoi ne réponds-tu pas et le PO peut accepter ta réponse?