comment appeller une méthode statique ?

yodarkyodark Membre
23:50 modifié dans API AppKit #1
Bonjour à  tous,

Je voudrais savoir comment faire pour appeler les méthodes d'une classe static ? Sans avoir a instancier un objet

Par exemple en java je peux faire Math.random() ce qui appelle la fonction random de la classe Math sans que j'aie besoin de créer un nouvel objet Math

Réponses

  • mpergandmpergand Membre
    23:50 modifié #2
    La même chose qu'en java !

    [NomObject methodeStatique];

    exemple avec + (NSView *)focusView  :
    NSView* view=[NSView focusView];
  • Philippe49Philippe49 Membre
    23:50 modifié #3
    dans 1235549138:

    Les méthodes d'une classe static ?


    Le vocabulaire utilisé en Objective-C dans ce cas, c'est méthode de classe
  • NoNo Membre
    23:50 modifié #4
    dans 1235550243:

    La même chose qu'en java !

    [NomObject methodeStatique];

    exemple avec + (NSView *)focusView  :
    NSView* view=[NSView focusView];


    Sauf qu'il faudrait plutôt écrire :
    [NomDeClasse methodeStatique];
    puisque c'est une méthode de classe comme l'a dit Philippe dans son message.
  • yodarkyodark Membre
    23:50 modifié #5
    Ok merci !

    Petite question à  ce même propos comment je fais pour creer une variable statique de classe ?

    Je voudrais y accéder en faisant MaClasse.maVariable

    J'ai pas vraiment trouvé compris comment on fait... La même chose que pour une variable normale ? Mais ca ne fonctionne pas :( Comment je l'initialise et comment y accéder ?
  • Philippe49Philippe49 Membre
    23:50 modifié #6
    +(TypeDeLaVariable) variableDeClasse {
      return variableDeClasse;
    }

    appel :
    [MaClasse variableDeClasse];

    Initialisation dans la méthode +(void) initialize


    Mais bon, ce n'est pas très Objective-C-friendly ... Pose-toi la question de l'utilité de cette variable de classe.
    On conseille plutôt de regrouper les variables globales dans un singleton.
  • GreensourceGreensource Membre
    23:50 modifié #7
    dans 1235669953:

    On conseille plutôt de regrouper les variables globales dans un singleton.

    Désoler mais je ne vois pas bien de quoi tu veux parler par singleton, tu aurais un exemple stp? Merci
  • Philippe49Philippe49 Membre
    février 2009 modifié #8
    D'abord voici comment créer ce singleton

    Conceptuellement, je ne vais pas me mouiller  :) , je copie la définitiion de WIkipédia :
    En génie logiciel, le singleton est un patron de conception (design pattern) dont l'objet est de restreindre l'instanciation d'une classe à  un seul objet (ou bien à  quelques objets seulement). Il est utilisé lorsque l'on a besoin d'exactement un objet pour coordonner des opérations dans un système.

    Par exemple [NSApplication sharedApplication] désigne l'unique instance de NSApplication dans le programme, [NSWorkspace sharedWorkspace] l'unique instance de NSWorkspace, [NSNotificationCenter defaultCenter] etc ...

    Dans un programme, un singleton peut être une instance fournissant un certain nombre de services visibles/transformables de l'ensemble des instances.
    Maintenant, par rapport à  tes besoins, à  toi de voir ...
  • GreensourceGreensource Membre
    23:50 modifié #9
    A ok, je n'avais pas compris que tu parlais de singleton. Mais c'est pas un peu lourd juste pour une variable de classe? J'ai cru voir quelques part sur ce forum que l'on pouvais "bidouiller" en déclarant cette variable dans l'implémentation?
  • Philippe49Philippe49 Membre
    février 2009 modifié #10
    dans 1235771720:

    A ok, je n'avais pas compris que tu parlais de singleton. Mais c'est pas un peu lourd juste pour une variable de classe? J'ai cru voir quelques part sur ce forum que l'on pouvais "bidouiller" en déclarant cette variable dans l'implémentation?

    Je ne connais pas ton projet, je dis seulement :
    dans 1235669953:

    Pose-toi la question de l'utilité de cette variable de classe.
    On conseille plutôt de regrouper les variables globales dans un singleton.


    Elle peut être utile, comme elle ne peut-être que bidouillage ou programme mal structuré, et que si Obj-C permet les variables de classe mais ne l'as pas prévu, c'est que ce n'est pas l'esprit du langage.
  • mpergandmpergand Membre
    23:50 modifié #11
    dans 1235771720:

    A ok, je n'avais pas compris que tu parlais de singleton. Mais c'est pas un peu lourd juste pour une variable de classe? J'ai cru voir quelques part sur ce forum que l'on pouvais "bidouiller" en déclarant cette variable dans l'implémentation?


    Super lourd je dirais  ;)

    Par exemple, on peut utiliser un singleton pour gérer les préférences d'une appli, c'est dans ce cas tout à  fait justifié.
    En plus avec les @property ça devient sympa à  utiliser:

    int valeur=[Preferences instance].valeur;

    Mais une variable static de classe n'est pas une variable globale à  l'appli mais à  la classe, donc l'utilisation d'un singleton n'a pas de sens.

    Je persiste à  utiliser le terme static car c'est vraiment le cas, ça colle comme de la glue  :)

    Si un object B hérite de A et les deux implémentent la même méthode de classe, pour appeler cette méthode on fait:

    [A methodeDeClasse];
    [B methodeDeClasse];

    Maintenant si on a une variable qui peut être A ou B, alors on doit faire:

    [[maVar class] methodeDeClasse];

    C'est vraiment collé à  la classe, c'est pas dynamique quoi, à  l'inverse du C++;

    maVarCPP.methodeDeClasse();  // ça appelle la bonne méthode directement

    Pour cette même raison, si on veut que B appelle la méthode de A, il faut faire:
    <br />// B<br />+(void) methodeDeClasse<br />{<br />&nbsp; [[self superclass] methodeDeClasse];&nbsp; // appelle de A<br />}
    



  • Philippe49Philippe49 Membre
    23:50 modifié #12
    dans 1235812354:

    Super lourd je dirais  ;)

    Non ce n'est pas per-lourd si on a pris l'habitude d'avoir dans son template de projet un singleton destiné à  ce genre de choses. A chaque création d'un nouveau projet le singleton est prêt, il ne reste plus qu'à  le remplir au fur et à  mesure des besoins.
    Cela n'apparaà®t lourd que la première fois. Mais cela dépend ce qu'on fait de cette variable de classe, effectivement.

    dans 1235812354:

    Par exemple, on peut utiliser un singleton pour gérer les préférences d'une appli, c'est dans ce cas tout à  fait justifié.

    Le singleton existe déjà  dans ce cas.


    dans 1235812354:

    <br />// B<br />+(void) methodeDeClasse<br />{<br />  [[self superclass] methodeDeClasse];  // appelle de A<br />}
    


    Tu es sur qu'il faille redéfinir la méthode pour simplement appeler l'implémentation de la classe parente ?
  • schlumschlum Membre
    23:50 modifié #13
    Un singleton est une variable static... C'est bonnet blanc, blanc bonnet...
    C'est juste une manière plus " Cocoa " de faire.
  • schlumschlum Membre
    23:50 modifié #14
    dans 1235813357:


    dans 1235812354:

    <br />// B<br />+(void) methodeDeClasse<br />{<br />&nbsp; [[self superclass] methodeDeClasse];&nbsp; // appelle de A<br />}
    


    Tu es sur qu'il faille redéfinir la méthode pour simplement appeler l'implémentation de la classe parente ?


    Non... Quand on sous-classe une vue, on ne redéfinit pas "setNeedsDisplay:" par exemple.
  • mpergandmpergand Membre
    23:50 modifié #15
    dans 1235813357:

    dans 1235812354:

    <br />// B<br />+(void) methodeDeClasse<br />{<br />&nbsp; [[self superclass] methodeDeClasse];&nbsp; // appelle de A<br />}
    


    Tu es sur qu'il faille redéfinir la méthode pour simplement appeler l'implémentation de la classe parente ?


    Dans ce cas où la méthode ne fait rien, c'est bien sûr inutile.

    Mais on peut imaginer que B récupère la valeur d'une variable statique de A et effectue un traitement à  partie de celle-ci.

    Il est vrai que au lieu de :
    [[self superclass] methodeDeClasse];  // appelle de A

    on peut faire:
    [A methodeDeClasse];

    Ce qui ressemble curieusement au C++, en fait !
    A::methodeDeClasse();
  • Philippe49Philippe49 Membre
    23:50 modifié #16
    dans 1235817030:

    on peut faire:
    [A methodeDeClasse];

    ou [B methodeDeClasse]
  • AliGatorAliGator Membre, Modérateur
    23:50 modifié #17
    Juste au passage : je suis en train de me metre à  sqlite et j'ai donc téléchargé un exemple Apple qui montre un peu comment faire. Ben dans cet exemple, pour éviter de préparer les requêtes SQL à  chaque fois qu'ils ont besoin d'en exécuter une, ils ont des variables statiques (variable de classe quoi) pour stocker le modèle de requête SQL dans leur classe Book. Ce qui leur permet d'avoir une requête précompilée et de la réutiliser à  chaque fois qu'ils ont besoin, en "bindant" juste les valeurs qu'il faut, plutôt que de recréer et recompiler la requête SQL à  chaque fois.

    // Static variables for compiled SQL queries. This implementation choice is to be able to share a one time<br />// compilation of each query across all instances of the class. Each time a query is used, variables may be bound<br />// to it, it will be &quot;stepped&quot;, and then reset for the next usage. When the application begins to terminate,<br />// a class method will be invoked to &quot;finalize&quot; (delete) the compiled queries - this must happen before the database<br />// can be closed.<br />static sqlite3_stmt *insert_statement = nil;<br />static sqlite3_stmt *init_statement = nil;<br />static sqlite3_stmt *delete_statement = nil;<br />static sqlite3_stmt *hydrate_statement = nil;<br />static sqlite3_stmt *dehydrate_statement = nil;
    
    ...<br />&nbsp; &nbsp; // This query may be performed many times during the run of the application. As an optimization, a static<br />&nbsp; &nbsp; // variable is used to store the SQLite compiled byte-code for the query, which is generated one time - the first<br />&nbsp; &nbsp; // time the method is executed by any Book object.<br />&nbsp; &nbsp; if (insert_statement == nil) {<br />&nbsp; &nbsp; &nbsp; &nbsp; static char *sql = &quot;INSERT INTO book (title) VALUES(?)&quot;;<br />&nbsp; &nbsp; &nbsp; &nbsp; if (sqlite3_prepare_v2(database, sql, -1, &amp;insert_statement, NULL) != SQLITE_OK) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NSAssert1(0, @&quot;Error: failed to prepare statement with message &#39;%s&#39;.&quot;, sqlite3_errmsg(database));<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; }<br />...
    
    Donc c'est pas parce qu'Apple le fait que c'est bien et parfait, on sait tous que parfois dans leurs exemples y'a pas toujours des trucs hypercleans (mais au moins il y a des exemples :)), mais tout ça pour dire que c'est quand même une pratique prévue.
  • mpergandmpergand Membre
    23:50 modifié #18
    Certains Ayatollahs du code (tous langages confondus) ont décrétés que les variables statiques c'était mal, sans aucunes raisons. Apple n'a pas grand chose à  voir la dedans.

    Maintenant, en Cocoa, il y a beaucoup de variables globales car ObjectiveC ne permet pas de faire autrement, par ex le nom des notifications pourraient être des variables statiques de la classe concernée (constantes de classes), mais le problème c'est qu'on peut pas y accéder directement comme en java ou C++:
    NSWindow.NSWindowDidCloseNotification;

    Pas possible en ObjC sans passer par une méthode (lourd !) d'où les variables globales.

  • Philippe49Philippe49 Membre
    février 2009 modifié #19
    dans 1235834088:

    Certains Ayatollahs du code (tous langages confondus) ont décrétés que les variables statiques c'était mal, sans aucunes raisons. Apple n'a pas grand chose à  voir la dedans.

    Le mot static ne signifie pas la même chose selon les langages. En C, et donc enObj-C , static signifie selon K&R :
    La déclaration static limite la portée de cet objet à  la suite du fichier source en cours de compilation.
    Je rajoute : et leur durée de vie est non limitée.
    Il faut reconnaà®tre qu'après cela en faire des variables vues de tous, c'est possible, mais c'est bizarre.


    dans 1235834088:

    NSWindowDidCloseNotification;

    Là  on a une constante. Si on veut limiter la portée d'une constante à  une unité de compilation, on mettra static éventuellement devant.

    dans 1235834088:

    Pas possible en ObjC sans passer par une méthode (lourd !) d'où les variables globales.

    Si c'est possible : dans le fichier déclarateur on met
           NSString * const MACHIN=@truc;
    sans static pour qu'il puisse être vu, et dans le fichier utilisateur
           extern NSString * const MACHIN;

    A noter que si on met static NSString * const MACHIN=@truc; la déclaration extern amène une erreur au linkage.
  • Philippe49Philippe49 Membre
    février 2009 modifié #20
    dans 1235832050:

    <br />static sqlite3_stmt *insert_statement = nil;<br />...<br />...
    
    Donc c'est pas parce qu'Apple le fait que c'est bien et parfait, on sait tous que parfois dans leurs exemples y'a pas toujours des trucs hypercleans (mais au moins il y a des exemples :)), mais tout ça pour dire que c'est quand même une pratique prévue.


    En même temps, SQLite est multi-langage, alors tout refaire pour Obj-C, et risquer des comportements différents ...
  • mpergandmpergand Membre
    23:50 modifié #21
    dans 1235842065:

    Le mot static ne signifie pas la même chose selon les langages. En C, et donc enObj-C , static signifie selon K&R :
    La déclaration static limite la portée de cet objet à  la suite du fichier source en cours de compilation.


    C'est bien là  le problème.

    dans 1235842065:

    mais de toute façon, il suffit qu'un autre fichier pose extern NSString * NSWindowDidCloseNotification; pour qu'il puisse utiliser ce symbole.


    C'est donc une variable globale.

    dans 1235842065:

    Si c'est possible : dans le fichier déclarateur on met
          NSString * const MACHIN=@truc;
    sans static pour qu'il puisse être vu, et dans le fichier utilisateur
          extern NSString * const MACHIN;


    Idem que précédemment.


  • NoNo Membre
    23:50 modifié #22
    dans 1235842065:

    Le mot static ne signifie pas la même chose selon les langages. En C, et donc enObj-C , static signifie selon K&R :
    La déclaration static limite la portée de cet objet à  la suite du fichier source en cours de compilation.
    Je rajoute : et leur durée de vie est non limitée.


    Je vais nuancer tes dires, Philippe :
    si techniquement parlant, static créé l'emplacement de la variable dans l'application heap (comme par ailleurs toute variable déclarée en dehors de toute fonction),
    déclarer une variable en static à  l'intérieur d'une fonction est un non-sens :
    en effet, sa visibilité sera uniquement que dans la fonction, et la décla en static interdira de la réutiliser même en utilisant extern dans le même fichier source (mais dans une autre fonction par exemple).
  • Philippe49Philippe49 Membre
    février 2009 modifié #23
    dans 1235848654:

    déclarer une variable en static à  l'intérieur d'une fonction est un non-sens :
    en effet, sa visibilité sera uniquement que dans la fonction, et la décla en static interdira de la réutiliser même en utilisant extern dans le même fichier source (mais dans une autre fonction par exemple).

    Sauf si on a besoin de la variable que dans la fonction, on utilise alors une variable statique pour sa qualité de durée de vie.
    Par exemple si on a besoin d'une fonction factorielle, on stocke dans un tableau les factoriels déjà  calculées et cela gagne du temps.
  • Philippe49Philippe49 Membre
    23:50 modifié #24
    dans 1235843675:

    C'est bien là  le problème.

    Quel problème ? c'est la règle du jeu du mot static en C. Ce n'est pas un problème, il suffit de ne pas mettre static, si on ne veux pas qu'une variable/fonction soit réservée à  l'unité de compilation.


    dans 1235843675:

    C'est donc une variable globale.
    ...
    Idem que précédemment.

    Non, c'est une variable accessible sur demande explicite, comme tout en C : On fait #include et on peut utiliser le matériel !
    Mais que pourrait-on vouloir d'autre ?
    Au programmeur de choisir une option entre
          des déclarations extern
          l'import d'un fichier de constantes
          l'import d'un fichier de variables gérées par un singleton
          le modèle des méthodes de classes décrit plus haut.
    selon ses besoins.

    Quand au titre du post, il montre bien l'ambiguité du mot statique selon les langages. En C, une méthode statique ne sera pas disponible justement si elle est précédée de static

    Ceci fonctionne
      NSString * standardMACHIN(void) ;  dans ClassA
      extern NSString * standardMACHIN(void) ;  dans ClassB

    Ceci ne fonctionne pas
      static  NSString * standardMACHIN(void) ;  dans ClassA
      extern NSString * standardMACHIN(void) ;  dans ClassB
  • schlumschlum Membre
    23:50 modifié #25
    dans 1235832050:

    Donc c'est pas parce qu'Apple le fait que c'est bien et parfait, on sait tous que parfois dans leurs exemples y'a pas toujours des trucs hypercleans (mais au moins il y a des exemples :)), mais tout ça pour dire que c'est quand même une pratique prévue.


    À vrai dire, je le trouve particulièrement crade  :)
    Utiliser "nil" à  la place de "NULL" déjà   :P
    Ensuite, la préparation de la requête, c'est peanuts face à  l'exécution... si c'est pour gagner 3 ms sur 5 s...
  • schlumschlum Membre
    23:50 modifié #26
    dans 1235834088:

    Certains Ayatollahs du code (tous langages confondus) ont décrétés que les variables statiques c'était mal, sans aucunes raisons. Apple n'a pas grand chose à  voir la dedans.

    Maintenant, en Cocoa, il y a beaucoup de variables globales car ObjectiveC ne permet pas de faire autrement, par ex le nom des notifications pourraient être des variables statiques de la classe concernée (constantes de classes), mais le problème c'est qu'on peut pas y accéder directement comme en java ou C++:
    NSWindow.NSWindowDidCloseNotification;

    Pas possible en ObjC sans passer par une méthode (lourd !) d'où les variables globales.


    ... qui sont généralement cachées par des singletons  :P

    Ce n'est pas sans aucune raison, le fait est que les variables statiques sont initialisées avant même l'entrée dans la fonction main. ça a peu de conséquences en C ou en Objective-C, mais en C++ avec des instances statiques ça peut donner des trucs terribles !
    Le fait est aussi que ça sort de la conception POO.
  • mpergandmpergand Membre
    février 2009 modifié #27
    dans 1235848985:

    dans 1235843675:

    C'est bien là  le problème.

    Quel problème ? c'est la règle du jeu du mot static en C.


    C'est bien un problème pour un langage dit orienté objet non ?

    Non, c'est une variable accessible sur demande explicite, comme tout en C : On fait #include et on peut utiliser le matériel !


    C'est valable pour tout y compris les classes ...

    Mais on tourne en rond, je dis qu'en ObjC il n'y a pas de vrai variable de classe et toi tu me dis qu'il suffit de les mettre externes, ce qui n'est pas très POO (comme dit schlum), en java pas possible de faire ce genre de bidouille infâme. :)

    Globalement, ObjC a de nombreuses lacunes:

    - pas de vrai variable de classe
    - pas de classe abstraite
    - pas de méthode abstraite
    - pas d'espace de nommage (bien regrettable !)

    Ce qui n'enlève rien aux qualités de Cocoa.



Connectez-vous ou Inscrivez-vous pour répondre.