typage statique et dynamique des arguments de méthodes

Philippe49Philippe49 Membre
juin 2007 modifié dans API AppKit #1
Le typage dynamique d'argument d'une méthode par id est connu
   type_retour maMéthode:(id) argument;
La définition se charge alors de réagir (peut-être) en fonction du type de l'argument.

Le typage statique possède également un aspect dynamique dans le sens où une méthode 
   type_retour maMéthode:(un_type) argument;
peut-être utilisée avec un argument qui appartient à  une sous-classe héritant de la classe un_type

Mieux encore, il semble que pour des méthodes de delegate d'une sous-classe, on puisse retyper les arguments par des sous-classes du typage standard. Je propose un essai où on redéfinit une delegate-method :
   - (NSSize)windowWillResize:(MyWindow *)sender toSize:(NSSize)proposedFrameSize

Ma question
Maintenant, constatant que cela fonctionne, j'ai du mal à  me représenter pourquoi cela marche sans le moindre warning sur la signature de la méthode du délégué.
Quelqu'un a-t-il une idée sur la question ?


<br /><br />@implementation AppController<br /><br />- (NSSize)windowWillResize:(MyWindow *)sender toSize:(NSSize)proposedFrameSize<br />{<br />	NSSize newSize;<br />	newSize.width=MIN(100.*lrint(proposedFrameSize.width/100.),1400.);<br />	newSize.height=MIN(100.*lrint(proposedFrameSize.height/100.),900.);<br />	[sender logName];<br />	NSLog(@&quot;new size : (%.2f,%.2f)&quot;,newSize.width,newSize.height);<br />	return newSize;<br />}<br />//=================================================<br />@implementation MyWindow<br />-(void) awakeFromNib<br />{<br />	name=[[NSString stringWithString:@&quot;SMURK&quot;] retain];<br />}<br />-(void) logName<br />{<br />	NSLog(name);<br />}<br />@end<br />



[Fichier joint supprimé par l'administrateur]

Réponses

  • schlumschlum Membre
    juin 2007 modifié #2
    Je crois que tu n'as pas bien saisi le concept de "id"  ;)
    Ce n'est pas du typage "dynamique" (tu ne pourras pas l'utiliser pour "int" par exemple)

    id veut simplement dire pointeur sur un objet...

    typedef struct objc_object {<br />	Class isa;<br />} *id;
    


    Donc il n'y a aucun problème pour faire un cast de id vers n'importe quelle pointeur d'instance et inversement (sans warning)

    Dans le runtime, tout est "id" pour les pointeurs d'instances de toute manière  :P
  • schlumschlum Membre
    22:46 modifié #3
    De même, quand tu parles de typage statique, ce n'est pas exact ; car il est impossible de déclarer une instance statique en Objective-C (contrairement au C++).
  • AliGatorAliGator Membre, Modérateur
    22:46 modifié #4
    Oui et puis je vois pas pourquoi tu pensais obtenir un Warning ?
    Ta méthode de delegate est tout a fait correcte, et quand ta NSWindow va essayer de voir si son deletage, donc ton AppController, répond à  [tt]- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)proposedFrameSize[/tt], autrement dit s'il peut envoyer un message de ce type au delegate, avec lui-même (self, ta MyWindow) en paramètre, et que ce dernier réponde, ben il va trouver une réponse positive dans ta méthode [tt]- (NSSize)windowWillResize:(MyWindow *)sender toSize:(NSSize)proposedFrameSize[/tt]. Vu que comme premier paramètre il va passer lui-même, qui est un MyWindow.

    Par contre si une NSWindow qui ne serait pas une MyWindow avait pour delegate ton AppController, là  on pourrait se demander comment ça va réagir, s'il va forcer l'appel en passant comme premier paramètre lui-même, NSWindow, en le castant en MyWindow (j'en doute très fort, le down-casting implicite étant interdit) ou s'il va simplement se dire qu'il ne trouve pas la méthode de delegate [tt]- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)proposedFrameSize[/tt] (plus probable  ;)).
  • Philippe49Philippe49 Membre
    juin 2007 modifié #5
    dans 1181991744:

    Je crois que tu n'as pas bien saisi le concept de "id"  ;)
    Ce n'est pas du typage "dynamique" (tu ne pourras pas l'utiliser pour "int" par exemple)


    Là  tu n'est pas d'accord avec Duncan (objective-C précis et concis, § typage dynamique).Voilà   ce qu'il dit page 34 :
    Utiliser id pour déclarer un pointeur vers un type d'objet indéfini ...
    Si à  l'exécution un objet ne possède la méthode ou le délégué approprié ... erreur


    Certes cela ne concerne que les objets, et donc pas les types C simples comme int, mais c'est clairement du typage dynamique, au sens qu'il est pris en compte à  l'exécution.

    dans 1181991744:

    De même, quand tu parles de typage statique, ce n'est pas exact ; car il est impossible de déclarer une instance statique en Objective-C (contrairement au C++).


    Là  encore, Duncan parle de typage statique, en ce sens qu'il est défini à  la compilation, et non a l'exécution.

    dans 1181991744:

    Dans le runtime, tout est "id" pour les pointeurs d'instances de toute manière

    Tu veux dire que les références aux méthodes sont recherchées à  l'exécution et non inscrites dans le code. Sans doute par rebond d'adressage
    isa --> adresse des méthodes

  • Philippe49Philippe49 Membre
    22:46 modifié #6
    dans 1181993760:

    Oui et puis je vois pas pourquoi tu pensais obtenir un Warning ?


    Ben parce que à  priori la déclaration dans la classe NSWindow de la méthode diffère de la redéfinition dans la sous-classe par le type du premier argument.
    Il me semblait que pour redéfinir une méthode dans une sous-classe, il fallait respecter la définition de cette méthode.
  • Philippe49Philippe49 Membre
    juin 2007 modifié #7
    dans 1181993760:


    Ta méthode de delegate est tout a fait correcte, et quand ta NSWindow va essayer de voir si son deletage, donc ton AppController, répond à  [tt]- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)proposedFrameSize[/tt], autrement dit s'il peut envoyer un message de ce type au delegate, avec lui-même (self, ta MyWindow) en paramètre, et que ce dernier réponde, ben il va trouver une réponse positive dans ta méthode [tt]- (NSSize)windowWillResize:(MyWindow *)sender toSize:(NSSize)proposedFrameSize[/tt]. Vu que comme premier paramètre il va passer lui-même, qui est un MyWindow.


    Oui, on voit bien par ton explication que cela fonctionne à  l'exécution.

    D'ailleurs, je viens d'essayer en mettant (NSString*) à  la place de (MyWindow*) et l'exécution est identique. Il y a cependant un warning à  la compilation disant que NSString ne réponds pas à  -logName.

    Faut-il comprendre (un peu comme le dit Schum dans sa dernière remarque) que le type des arguments de la méthode ne sont utiles qu'au programmeur afin de lui éviter des bugs ?
    Ou est-ce que comme souvent dans les langages dérivant du C, il s'agit de tolérances non inscrites dans la norme, et donc non fiables ?
  • schlumschlum Membre
    22:46 modifié #8
    dans 1181995029:

    dans 1181991744:

    Je crois que tu n'as pas bien saisi le concept de "id"  ;)
    Ce n'est pas du typage "dynamique" (tu ne pourras pas l'utiliser pour "int" par exemple)


    Là  tu n'est pas d'accord avec Duncan (objective-C précis et concis, § typage dynamique).Voilà Â  ce qu'il dit page 34 :
    Utiliser id pour déclarer un pointeur vers un type d'objet indéfini ...
    Si à  l'exécution un objet ne possède la méthode ou le délégué approprié ... erreur


    Certes cela ne concerne que les objets, et donc pas les types C simples comme int, mais c'est clairement du typage dynamique, au sens qu'il est pris en compte à  l'exécution.


    Les mots "statique" et "dynamique" sont mal choisis alors... Une définition est toujours statique. Dans le runtime Obj-C, tous les pointeurs vers objets sont transformés en "id" et c'est du statique. C'est comme quand on dit "void*" pour n'importe quel pointeur...
    D'ailleurs "id" est un void* (entre autres) puisque c'est un struct *...
    Le seules différences sont au niveau de la compilation... À l'exécution, ça se passe exactement pareil si tu mets "id" ou "NSObject*" ou "NSString*".


    dans 1181991744:

    De même, quand tu parles de typage statique, ce n'est pas exact ; car il est impossible de déclarer une instance statique en Objective-C (contrairement au C++).


    Là  encore, Duncan parle de typage statique, en ce sens qu'il est défini à  la compilation, et non a l'exécution.

    dans 1181991744:

    Dans le runtime, tout est "id" pour les pointeurs d'instances de toute manière

    Tu veux dire que les références aux méthodes sont recherchées à  l'exécution et non inscrites dans le code. Sans doute par rebond d'adressage
    isa --> adresse des méthodes


    L'appel des méthodes sont transformés en appels objc_msgSend(id,SEL,...)

    Donc au niveau de l'exécution, il se fiche complètement du type et de la méthode. Si c'est pas défini, il envoie une exception et crashe.
  • Philippe49Philippe49 Membre
    juin 2007 modifié #9
    dans 1181995954:


    L'appel des méthodes sont transformés en appels objc_msgSend(id,SEL,...)

    Donc au niveau de l'exécution, il se fiche complètement du type et de la méthode. Si c'est pas défini, il envoie une exception et crashe.


    Ok: SEL permet la recherche de l'adresse du code de la méthode pour la classe via isa 
    Les arguments sont données par une liste variable d'arguments, et la méthode a sans doute stocké dans son code la taille utile (en octets) pour chacun d'entre eux ..
    Bon cela semble marcher
  • Philippe49Philippe49 Membre
    22:46 modifié #10
    dans 1181995954:

    Les seules différences sont au niveau de la compilation... À l'exécution, ça se passe exactement pareil si tu mets "id" ou "NSObject*" ou "NSString*".


    Tu confirmes la réponse que j'ai faite à  Aligator.
  • schlumschlum Membre
    juin 2007 modifié #11
    Euh... Je dirais que c'est plutôt IMP qui est un pointeur direct sur la fonction ; SEL est de plus haut niveau.

    C'est d'ailleurs ce système qui fait que l'Objective-C ne tient pas la vitesse sur des algorithmes hautement récursifs (si on le fait avec des objets...), comme les algos Alpha-Bêta par exemple.
    Le C est beaucoup plus rapide sur l'appel des fonctions, et le C++ sur l'appel de méthodes.

    J'avais fait quelques tests ici :
    http://forum.macbidouille.com/index.php?s=&showtopic=199794&view=findpost&p=2016183
    http://forum.macbidouille.com/index.php?s=&showtopic=199794&view=findpost&p=2017000
  • schlumschlum Membre
    22:46 modifié #12
    dans 1181996919:

    dans 1181995954:

    Les seules différences sont au niveau de la compilation... À l'exécution, ça se passe exactement pareil si tu mets "id" ou "NSObject*" ou "NSString*".


    Tu confirmes la réponse que j'ai faite à  Aligator.


    Oui
  • Philippe49Philippe49 Membre
    22:46 modifié #13
    Merci de ces précisions.
Connectez-vous ou Inscrivez-vous pour répondre.