Comment hérite-t-on d'une méthode de classe ?
colas_
Membre
J'ai une classe B qui hérite d'une sous-classe de A.
J'ai une méthode de A :
+ (id) insertInManagedObjectContext
Je souhaite la réécrire dans B.
Est-ce que je peux écrire
(1)
+ (id)insertInManagedObjectContext
{
self = [super insertInManagedObjectContext] ;
// ...
return self ;
}
? Et, si non, pourquoi ?
Ou dois-je plutôt écrire :
(2)
+ (id)insertInManagedObjectContext
{
id myNewInstance = [super insertInManagedObjectContext] ;
// ...
return myNewInstance ;
}
? Le problème de cette méthode est que myNewInstance étant un id, le compilteur ne validera si j'applique à myNewInstance des méthodes spécifiques à classeA ou classeB.
J'imagine que
(3)
+ (id)insertInManagedObjectContext
{
classeA *myNewInstance = [super insertInManagedObjectContext] ;
// ...
return myNewInstance ;
}
est faux, par ailleurs ; car le type attendu par la méthode est (id) et non (classeA).
Donc, la bonne solution est-elle
(4)
+ (id)insertInManagedObjectContext
{
classeB *myNewInstance = [super insertInManagedObjectContext] ;
// ...
return myNewInstance ;
}
?
Merci !
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Dans classe B:
insertInManagedObjectContext te renverra un objet de type A. Tu dois pouvoir caster le retour en type B (ou id) à condition qu'il n'y ai pas de variables d'instance dans B (étant donné qu'il n'y aura pas eu d'allocation d'instance de B .
(4) me paraà®t donc valide sous certaine condition...
Cependant il y a bien certaine proposition qui sont vraiment à proscrire : Ici "self" fait référence à ta ClasseB. En objective-C, les classes sont aussi des objets de type "Class".
Donc ça fonctionne car grâce au typage dynamique tu peux assigner n'importe quel objet à ta variable, mais changer la valeur de self est vraiment une très mauvaise idée ici. Je sais pas si ça peut planter ou provoquer des comportements inattendu, mais c'est vraiment à ne pas faire. Ici c'est techniquement le code le plus correct. Mais comme tu le souligne, ton objet n'étant pas typé, quand tu appelleras des méthodes de ta ClasseB sur ton objet, tu auras potentiellement des warnings, voire des erreurs de compilation si tu utilises ARC. Ici c'est juste un problème de sémantique. C'est correct car l'objet retourné est une sous-classe de ta ClasseA, donc tu n'auras aucune soucis. C'est juste pas vraiment logique d'utiliser ce code dans ta ClasseB. De plus, comme avec "id" tu ne pourras pas appeler des méthodes de ta ClasseB. Compte tenu de tout ce qui a été dit, c'est effectivement la meilleure solution. Tu pourras appeler sur ton objet n'importe quelle méthode de ta classeB.
Merci !
Ca ne ressemble pas en grand chose cette méthode.
Ca pourrait ressembler à une méthode de commodité, mais ça ne respecte pas les règles de nommage.
Une méthode de commodité porte le nom de la classe à instancier.
Je ne suis pas d'accord avec ton implémentation de ta méthode de commodité mpergrand
Justement je mettrais pas [ClassA alloc] mais [self alloc]
Comme ça si tu fais une sous-classe SousClasseA qui hérite de ClassA, quand tu vas appeler la méthode de commodité sur SousClasseA ça va bien créer une instance de SousClasseA et pas de ClassA
Par exemple si tu appelles [NSMutableString string] ça te retourne bien une instance de NSMutableString, et pas de NSString,pourtant la méthode +string n'est sans doute implémentée que dans NSString (avec un "return [[[self alloc] init] autorelease];") et pas surchargée dans NSMutableString.
Elle serait implémentée avec un "return [[[NSString alloc] init] autorelease];" alors un [NSMutableString string] retournerait une instance de NSString et pas de NSMutableString.
Salut Aligator,
Je suis d'accord avec toi et c'est ce que j'avais fait initialement, mais ici on a une méthode qui désigne un type de classe précis( classA et classB) et une méthode classA qui retourne un objet de classB c'est assez bizarre ...
Le but était aussi de montrer l'aspect statique des méthode de classes.
Une autre solution, bien meilleur, serait d'implémenter par exemple une méthode new:
et voila, mais c'est un peu ballot car new existe déjà pour NSObject
et en regardant la doc, il y a un exemple intéressant d'utilisation de new:
However, there's little point in implementing a new... method if it's simply a shorthand for alloc and init..., as shown above. Often new... methods will do more than just allocation and initialization. In some classes, they manage a set of instances, returning the one with the requested properties if it already exists, allocating and initializing a new instance only if necessary. For example:
dont colas2 pourrait peut-être s'inspirer si tant est que je puisse comprendre ce que colas2 veut faire vraiment ...
Oui en fait en rédigeant ma réponse, j'étais sûr que tu allais me dire ça, que puisque la méthode s'appelle classA ça ferait bizarre de retourner une instance d'autre chose que ClassA
Mais en fait ça dépend des vrais noms de classA et classB.
C'est d'ailleurs pour ça que j'ai pris l'exemple ensuite de NSMutableString vs. NSString. Si le vrai terme à la place de "classB" c'est un terme qui est bien un sous-ensemble de "classA" par exemple si tu remplaces "classA" par "Parser" et ses sous-classes classB et classC par "XMLParser" et "JSONParser", alors c'est logique que la méthode "+[Parser parser]" retourne un XMLParser ou un JSONParser selon si elle est appelée sur la sous-classe correspondante, plutôt que de retourner une instance de la classe mère Parser dans laquelle est implémentée la méthode "parser".
Et en pratique j'ai rarement voire jamais vu de cas où il était utile de créer une méthode de classe qui retourne une classe spécifique (une des classes parentes explicitement) plutôt que la classe sur laquelle on l'appelle.
Quel intérêt si tu as ClassB qui hérite de ClassA d'avoir une méthode "classA" définie dans ClassA... qui retourne forcément un ClassA dans tous les cas ? Je veux dire si tu veux une instance de ClassA, tu vas pas faire [ClassB classA] en te disant que même appelé sur la sous-classe ClassB ça retournera un ClassA... quitte à vouloir une instance de ClassA, tu vas appeler [ClassA classA], pas [ClassB classA], non ? Donc j'ai du mal à voir un cas d'usage où ça serait utile.
Oui, moi aussi, c'était un exemple très théorique ...
Et d'ailleurs, je me suis dit que c'est ce que l'on ferait en C++ ou en Java ou le mot clef this ne peut s'utiliser que sur une instance (si je ne me trompe pas)
En c++ on utilise l'opérateur ::
ce qui en ObjC s'écrit: [NomClasse nomMéthode]
s'écrirait en C++: NomClasse::nomMéthode()
Ca n'a pas la souplesse du self en ObjC, c'est vraiment du statique !
Overrider dans une sous-classe la méthode + (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_;
écrite par moGenerator.