typage statique et dynamique des arguments de méthodes
Philippe49
Membre
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 ?
[Fichier joint supprimé par l'administrateur]
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(@"new size : (%.2f,%.2f)",newSize.width,newSize.height);<br /> return newSize;<br />}<br />//=================================================<br />@implementation MyWindow<br />-(void) awakeFromNib<br />{<br /> name=[[NSString stringWithString:@"SMURK"] retain];<br />}<br />-(void) logName<br />{<br /> NSLog(name);<br />}<br />@end<br />
[Fichier joint supprimé par l'administrateur]
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
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...
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
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 ).
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.
Là encore, Duncan parle de typage statique, en ce sens qu'il est défini à la compilation, et non a l'exécution.
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
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.
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 ?
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*".
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
Tu confirmes la réponse que j'ai faite à Aligator.
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
Oui