Selector ou pas ?
Okidoki
Membre
Bonjour,
J'aimerais savoir comment appeler dynamiquement la methode d'une classe (disons la classe "employe") dans la methode d'une autre classe (la classe "entreprise").
L'idée est la suivant: la classe "entreprise" ayant comme attribut un tableau d'objets de type "employe" (NSMutableArray), et chacun des employés répondant à des méthodes (telles que "salaire" ou "cotisations"), je cherche à écrire une méthode générique de la classe "entreprise" qui me permettrait d'avoir la somme (sur tous les employés) des salaires et des cotisations sans devoir écrire une fonction pour chacun des attributs. Autrement dit, j'aimerais avoir une méthode dans la classe "entreprise" dans laquelle je puisse passer la méthode d'une autre classe en argument. J'ai tenté çà (quelques lignes de code valent mieux que mille mots...):
Dans "employe":
- (int) salaire
{
return salaire;
}
Dans "entreprise":
- (int) sumStat:(SEL)stat
{
int nbEmployes = [employes count];
int i;
int total = 0;
for (i = 0; i < nbEmployes; i++)
{
total = total + (int)[[employes objectAtIndex:i] stat];
}
return total;
}
- (int) sumSalaires
{
SEL action = @selector (salaire);
return [self sumStat: action];
}
Et dans "employe":
- (int) salaire
{
return salaire;
}
Ca ne fonctionne pas. Quelqu'un aurait-il une idée ?
Merci d'avance !
J'aimerais savoir comment appeler dynamiquement la methode d'une classe (disons la classe "employe") dans la methode d'une autre classe (la classe "entreprise").
L'idée est la suivant: la classe "entreprise" ayant comme attribut un tableau d'objets de type "employe" (NSMutableArray), et chacun des employés répondant à des méthodes (telles que "salaire" ou "cotisations"), je cherche à écrire une méthode générique de la classe "entreprise" qui me permettrait d'avoir la somme (sur tous les employés) des salaires et des cotisations sans devoir écrire une fonction pour chacun des attributs. Autrement dit, j'aimerais avoir une méthode dans la classe "entreprise" dans laquelle je puisse passer la méthode d'une autre classe en argument. J'ai tenté çà (quelques lignes de code valent mieux que mille mots...):
Dans "employe":
- (int) salaire
{
return salaire;
}
Dans "entreprise":
- (int) sumStat:(SEL)stat
{
int nbEmployes = [employes count];
int i;
int total = 0;
for (i = 0; i < nbEmployes; i++)
{
total = total + (int)[[employes objectAtIndex:i] stat];
}
return total;
}
- (int) sumSalaires
{
SEL action = @selector (salaire);
return [self sumStat: action];
}
Et dans "employe":
- (int) salaire
{
return salaire;
}
Ca ne fonctionne pas. Quelqu'un aurait-il une idée ?
Merci d'avance !
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Voyez la famille "performSelector" pour les cas simple, et tournez-vous du côté de NSInvocation pour des cas comme le votre où vous vous intéressez à la valeur de retour.
Ma réponse est un peu évasive, mais si vous avez un problème, n'hésitez pas à reposter.
+
Chacha
[tt]NSLog(@%@",[monEntreprise valueForKeyPath:@employes.@sum.salaire"]);[/tt]
Le code de Renaud doit normalement résoudre le problème, mais ton code Okidoki me parait curieux pour un traitement aussi classique, je pense que tu n'es pas trop familiarisé avec la notion de méthode accesseur et tu as essayé de te débrouiller avec @selector().
Il te faut faire un outlet de la classe Entreprise vers la classe Employé, puis mettre la directive #import "Employe.h" dans ton fichier "Entreprise.h". Et là tu peux accéder à toutes les méthodes ta classe "Employé". Le code devrait ressembler à ça (j'ai volontairement omis le NSEnumerator à la place de la boucle For) :
[tt]
-(int)sumStat
{
  int nbEmployes = [employes count];
  int i;
  int total = 0;
 Â
  for (i = 0; i < nbEmployes; i++)
  {
   total = total + [[employes objectAtIndex:i] salaire];
  }
  return total;
}
-(int)sumSalaires
{
  return [self sumStat];
}
[/tt]
Je me demande aussi pourquoi 2 méthodes différentes alors qu'une seule suffirait. En fin de compte, c'est le problème classique de communication entre classes. Cela me rappel un topic, tu peux aller voir ici et télécharger le petit projet d'exemple. Si tu as des questions n'hésites pas...:)
Bon, il est tard, j'espère que je n'ai rien oublié ??
Ha si, bienvenue sur OC Okidoki, et là je pense que pour fêter ton arrivée sur OC, tu ne pourrais pas faire mieux que d'offrir une tournée générale (ce qui serait un minimum) !
J'utilise donc cette simple ligne:
sommeSalaires = [[employes valueForKeyPath:@"@sum.salaire"] intValue];
Je venais aussi de découvrir la classe NSEnumerator dont parle Eddy. ça ne change pas grand chose à la concision du code, mais c'est toujours bon à savoir.
Pour la tournée générale, habillez-vous chaudement, c'est au Québec que ça se passe !
Je maà®trise pas encore trop trop les KeyPath, sur le principe j'ai compris, genre si ta classe entreprise a une variable d'instance patron (de la même classe que employés, pour faire simple), je comprend que [monEnterprise valueForKeyPath:@patron.salaire] qui en somme est équivalent (mais plus court) à [[monEntreprise valueForKey:@patron] valueForKey:@salaire]; et que grace au KVC ça accède directement aux variables d'instances (par l'accesseur dédié s'il existe et a un nom standard, ou par accès direct sinon).
Bref tout ça j'ai bien compris... mais c'est ton "@sum" du coup qui me trouble. Le "@" devant j'imagine que c'est pour préciser qu'il s'agit d'un @selector mais ce selector, tu dois le définir ou il est prédéfini dans Cocoa pour faire la somme des valeurs de la clé suivante dans le KVP, ou un truc du genre ?
Déjà à quoi est équivalent ton KVP ?
[[monEnterprise valueForKey:@employees] performSelector:@selector(sum) withObject:@salaire]; ? Un truc du genre ?
Sinon, en code normal, ce serait plutot équivalent à un hypothéthique:
[tt][[monEnterprise valueForKey:@employees] sumOfValuesForKey:@salaire];[/tt]
@okidoki
Si tu peux utiliser une valeur SEL sur un objet, il faut utiliser la méthode performSelector:.
[tt]- (int) sumStat:(SEL)stat
{
  int nbEmployes = [employes count];
  int i;
  int total = 0;
 Â
  for (i = 0; i < nbEmployes; i++)
  {
   total += (int)[[employes objectAtIndex:i] performSelector:stat];
    // a = a + b; peut s'écrire a+=b;
  }
  return total;
}[/tt]
Par exemple, l'autre jour j'avais un tableau de NSNumber, et je voulais calculer la somme de son contenu.
C'est quoi la solution?
[mon tab valueForKey:@"@sum.floatvalue"] ?
[mon tab valueForKey:@floatvalue.@sum"] ?
Là tout de suite je ne peux pas vérifier, mon powerbook est parti chez le docteur :-(
+
Chacha
[monTab valueForKeyPath:@"@sum.self"];
Alors:
1. mon tab en un mot
2. valueForKeyPath et pas valueForKey (les opérateurs ne fonctionnent qu'avec les keypath).
enfin le sérieux: 3. l'opérateur @sum ne fonctionne qu'avec des objets, en passant par floatValue, tu reviens à un type "primitif" qu'il ne sait pas gérer. Je dirais aussi que le passage par floatValue n'est pas nécessaire car c'est à NSNumber d'effecteur les conversions des différents types de nombres, donc tu mets "self" pour dire d'additionner les nombres directement entre eux.
voili voulou.
+
Chacha
PS : En tous cas, merci ! et ne t'inquiète pas pour les smileys, ça doit être la fatigue
tssss c'est pô bien ça, faire des fôtes aussi basiques
Ralala... faut arrêter les , hein Renaud ? ;D
[/PJ]