7
votes

Objectif C Héritage de classe C avec méthodes d'usine

Je voudrais hériter d'une classe-cadre qui a une méthode d'usine. Comment puis-je rendre la méthode d'usine renvoyer un objet de mon type de classe hérité? J'ai trouvé Cet article utile qui décrit une situation similaire, mais dans leur cas, vous avez le contrôle de la superclasse. Comment pourrais-je écrire, dire, une sous-classe de uiimage que Imagenamed: retournerait un objet de mon type de sous-classe?


3 commentaires

Peut-être que vous pouvez réaliser ce que vous voulez en écrivant une catégorie sur uiimage?


Oui, je pense maintenant à ce sujet. Seulement que j'ai besoin de membres supplémentaires de classe (propriétés) et que je voulais éviter les tracas avec objc_setstaSociatedObject et amis. En outre, parce que je ne trouve pas qu'il est élégant de créer une solution de contournement de ce type pour un problème complètement différent. Cependant, je crains de plus en plus que je n'ai pas d'autre choix.


Jetez un coup d'oeil à ce NsObject Catégorie. Les deux méthodes SetRuntimeProperty: Nom: et RuntimeProperty: Aide à la convinient Set et accédez aux objets associés.


3 Réponses :


3
votes

Pour votre exemple:

  • Sous-classe uiimage à, dites, myImage
  • Implémentez le Imagenamed: Méthode pour effectuer quelque chose de spécifique que vous devez être effectué.
  • appelez cette méthode sur cette classe: myImage * newImage = [myImage Imagenamed: Imagename];

4 commentaires

Cela ne vous aidera pas vraiment, car vous ne pouvez pas appeler super dans votre propre implémentation de ImagenameMamed , car cela finira par retourner une instance de type uiimage .


Qui a dit qu'il a besoin d'appeler super? Il peut alloc et init un objet de sa sous-classe dans le cadre de la méthode et de retourner cela. Et, comme nous le savons tous, la convention est pour les sous-classes d'appeler l'initialiseur désigné de leur Superclass, qui renvoie un objet de type ID . Quoi qu'il en soit, il s'agit d'un exemple de force basé sur ce que l'OP a demandé. Les détails sont laissés à l'utilisateur, mais le principe d'un constructeur de commodité Alloc et d'un objet de sa propre classe est sonore.


Oui, mais dans ce cas, la "magie" Apple fait dans Imagenamed: est très utile et je ne pense pas qu'il veuille mettre en œuvre cela par lui-même. Mais vous avez raison, votre réponse n'est pas "erronée" mais je pense pas très utile dans ce cas.


Mon problème particulier est que je ne veux pas fournir une mise en œuvre alternative d'Imagenamed, ce serait bien pour moi tel qu'il est si cela renvoie une instance myImage. Et UiImage n'a pas une init ... Méthode analogique à l'imagenamed: cela considère également la mise en cache d'image afin que je ne puisse même pas le remplacer en gardant la même fonctionnalité - comme le dit Jonathan.



0
votes

L'approche qui résolvait mon problème était d'utiliser une catégorie au lieu d'héritage (les crédits vont à Jonathan cichon dans les commentaires de ma question). J'ai utilisé Références associatives Pour déclarer et stocker des données supplémentaires dans la mise en œuvre de la catégorie comme indiquée beaucoup ici. J'aimerais attirer l'attention sur le NsObject Mise en œuvre de la catégorie proposée par Jonathan qui rend vraiment facile et élégant d'ajouter des références associatives à n'importe quel objet.


4 commentaires

Pendant que je suis content que vous ayez résolu votre problème - votre question portait sur des constructeurs de commodité primordiques, que vous avez ensuite changé pour une question sur l'ajout de stockage à une classe en dehors d'une extension de classe. Donc, il y a vraiment deux séries de questions et de réponses en même temps.


J'avais besoin d'étendre la classe-cadre d'origine avec des données supplémentaires et de pouvoir utiliser ses constructeurs de commodité d'origine. Quand j'ai posé une question à la question originale, je ne savais pas comment faire cela et supposé qu'il puisse être atteint avec héritage. Vous avez raison du point de vue que je n'avais pas précisé que je dois ajouter des données supplémentaires à la classe, mais écrivit "héritage". D'autre part, la solution de Jonathan résout parfaitement mon problème, même s'il n'utilise pas l'héritage.


NB: Je n'ai pas changé la question initiale et ajouté le conseil d'Associ.RFS dans cette réponse uniquement comme référence pour les futurs lecteurs.


Je souligne que ce que vous avez demandé et ce que vous vouliez vraiment savoir était deux choses séparées.



10
votes

Je voudrais hériter d'une classe-cadre qui a une méthode d'usine. Comment puis-je rendre la méthode d'usine renvoyer un objet de mon type de classe hérité? P>

C'est tout ce que vous devriez em> doit faire: p> xxx pré>

alors: p> xxx pré>


Comment pourrais-je écrire, disons, une sous-classe d'uiimage que l'imagenamed: retournerait un objet de mon type de sous-classe? P> blockQuote>

+ [UIIMAGE Imagenamed:] Code> La mise en œuvre de celle-ci a écrit des sous-classeurs hors de cette approche. Par conséquent, vous auriez besoin de mettre en œuvre cette méthode vous-même. P>

Voici comment oi em> devrait déclarer une méthode d'usine: p> xxx pré>

et Comment-on devrait em> l'implémenter: p> xxx pré>

mais ils ne l'ont pas fait de cette façon - + [UIIMAGE Imagenamed:] Code > a écrit des sous-classes et renvoie un uiimage code> lorsque vous écrivez monimage * img = [monimage Imagenamed: pname]; code>. Parfois cela se fait pour une bonne raison. Certaines méthodes devraient avoir une sémantique "finale". Cela apparaît souvent lorsque votre méthode peut renvoyer plusieurs types, comme dans un cluster de classe. La langue n'exprime pas les méthodes "finales" - mais une telle méthode doit au moins être documentée. P>


de sorte de venir sur ce uiImage code> cas: p >

@interface MONImage : UIImage

+ (instancetype)imageNamed:(NSString *)pName;

@end

@implementation MONImage

+ (instancetype)imageNamed:(NSString *)pName
{
    UIImage * source = [UIImage imageNamed:pName];
    CGImageRef cgImage = source.CGImage;
    if (cgImage)
        return [[self alloc] initWithCGImage:cgImage];
    // try it another way
    return nil;
}

@end


2 commentaires

Cela fournit-il également le comportement de mise en cache de [uiimage Imagenamed:] ? Sinon, vous devriez peut-être stocker une référence à l'image d'origine dans monimage . Mais vraiment belle solution.


@Jonathancichon, il conserverait le comportement de recherche de + imagenamed: . Il chargerait l'image, puis le cache. Le comportement exact de la mise en œuvre de la mise en cache est abstraité, alors ma conclusion est qu'il n'est pas garanti d'être identique à cet égard. Je suppose Ce serait la même chose en ce qui concerne la mise en cache, mais je n'ai pas prouvé cela. bonne question.