Débat Objective-C 2.0

245

Réponses

  • NseaProtectorNseaProtector Membre
    06:24 modifié #32
    Et bien, ça débat sec, c'est intéressant en tout cas et cela démontre la souplesse de Cocoa. J'aimerais bien l'avis d'un Chacha et d'un Philippe49. Maintenant c'est peut-être a chacun de faire ses choix en fonction de ses affinités...
  • schlumschlum Membre
    06:24 modifié #33
    dans 1228997432:

    L'itération consiste simplement à  "récupérer" la totalité du contenu d'une collection, dans le cas d'un NSArray tu veux récupérer les valeurs (et donc seulement des valeurs) dans un ordre précis, quitte à  le faire dans le désordre un NSSet est plus rapide...
    Dans le cas d'un dictionnaire, tu veux savoir quelles sont les clés utilisées et quelles sont les valeurs qui leur sont associées : "tiens, ce dictionnaire concurrent définit ces 3 mots avec ces définitions, moi j'ai 4 mots dont 2 sont dans l'autre dictionnaire, et les définitions ne sont pas les mêmes !".


    Ah ben non, pas NSSet puisqu'il faut conserver les couples clé / valeur côté à  côte !

    En gros, si je veux itérer un truc créé avec "+ (id)dictionaryWithObjectsAndKeys:(id)firstObject , ..."
    Autant le faire sur l'array équivalent "+ (id)arrayWithObjects:(id)firstObj, ..."
    Au moins on ne crée pas de table de hashage inutile...
  • psychoh13psychoh13 Mothership Developer Membre
    décembre 2008 modifié #34
    dans 1228998051:

    Ah ben non, pas NSSet puisqu'il faut conserver les couples clé / valeur côté à  côte !

    En gros, si je veux itérer un truc créé avec "+ (id)dictionaryWithObjectsAndKeys:(id)firstObject , ..."
    Autant le faire sur l'array équivalent "+ (id)arrayWithObjects:(id)firstObj, ..."
    Au moins on ne crée pas de table de hashage inutile...


    Déjà  il faut savoir qu'un NSArray est aussi implémenté sous forme de table de hashage, aussi bizarre que cela puisse paraà®tre, et ça on le sait parce que NSArray utilise un CFArray sous le capot et que CFArray est open-source... Ensuite, ce serait plus ou moins valable si on ne voulait que itérer dans le dictionnaire, mais bon à  mon avis c'est beaucoup plus subtile que ça... Après tout est une question de choix, après tout, personnellement je n'utilise pas souvent de dictionnaire, mais dans certain cas c'est plus pratique d'utiliser un dictionnaire et d'itérer tous les couples clés/valeurs sans avoir à  se soucier de la récupération simultanée de deux objets qui se suivent dans un NSArray.

    Surtout, je rappelle ce qui a lancé le sujet des itérations de dictionnaires, c'est le système de block qui te fourni les deux objets simultanément, si t'avais envie d'utiliser une boucle à  peu près normale avec un array où la clé et la valeur sont sur deux index successifs, tu aurais à  faire deux itérations par couple OU ce qui n'est EN RIEN plus efficace prendre dans une itération à  la fois la valeur T et la valeur T+1... Alors, qu'une boucle d'itération qui te retourne les deux éléments en même temps et qui en plus est beaucoup plus optimisé du fait qu'elle a un accès direct à  la structure interne... Selon moi c'est beaucoup mieux... Personnellement, je trouve le dictionnaire plus pratique, enfin ce n'est que mon avis...
  • psychoh13psychoh13 Mothership Developer Membre
    06:24 modifié #35
    Juste une petite remarque sur le sujet, c'est pas vraiment un débat sur Objective-C 2.0 c'est plutôt un débat sur les nouveautés introduites par Apple, parce que le système de blocks n'est pas spécifique à  ObjC, c'est une fonctionnalité intégrer à  C et à  C++ et qui est de facto disponible en Objective-C et en Objective-C++.
  • schlumschlum Membre
    décembre 2008 modifié #36
    Mais les closures ne sont en fait qu'une simplification syntaxique des callbacks... On peut faire exactement la même chose sans, en définissant une callback objet qui prend dans son constructeur les variables du contexte dont on a besoin (ou une callback non objet en ajoutant un contexte argument).
    Vu qu'ils n'ont pas implémenté de listing de NSArray / NSDictionary avec callback, pourquoi le feraient-ils avec les closures ?

    Enfin... En général à  partir du moment où on commence à  avoir besoin de pinailler sur la vitesse d'itération, il vaut mieux passer à  un autre langage que l'Objective-C je pense.
  • psychoh13psychoh13 Mothership Developer Membre
    décembre 2008 modifié #37
    dans 1229001340:

    Mais les closures ne sont en fait qu'une simplification syntaxique des callbacks... On peut faire exactement la même chose sans, en définissant une callback objet qui prend dans son constructeur les variables du contexte dont on a besoin (ou une callback non objet en ajoutant un contexte argument).
    Vu qu'ils n'ont pas implémenté de listing de NSArray / NSDictionary avec callback, pourquoi le feraient-ils avec les closures ?


    Déjà , une chose est sûre et certaine, ils l'ont fait.

    Ensuite, ils ont implémenté les closures/blocks justement pour ce genre de fonctionnement, justement pour supprimer les callbacks qui sont loin d'être aussi pratique...
    En effet tu pourrais faire un callback type objet, mais question optimisation ce n'est pas pratique, et surtout, tu vas t'amuser à  créer une classe spécifique pour chaque context de ton application ? Non, je ne crois pas...

    Ce qui est fait actuellement pour les callbacks c'est :
    • Aucune information de context ; par exemple dans l'algorithme de tri de NSArray, qui demande un selecteur sur une méthode prenant en paramètre l'objet à  comparer et rien d'autres, pas d'info de contexte.
    • Un objet personnalisé ou un dictionnaire de données, typiquement NSTimer et NSThread.
    • Un pointeur sur void, permettant de mettre n'importe quel structure valeur simple ou même objet comme context, typiquement les fonctions de callbacks existantes dans Core Foundation ou Core Graphics.


    Alors soit tu n'as pas d'information de context, soit ta méthode doit prendre un paramètre de plus ou alors tu dois stocker ce paramètre dans l'objet qui va appeler la méthode et se passer lui-même en paramètre.
    Dans les 3 cas il faut que ce soit prévu par l'interface pour permettre l'utilisation d'informations de context. L'avantage des blocks c'est que l'implémenteur n'a pas besoin de savoir quels informations tu veux passer, elles sont dans la portée du block directement, et la méthode utilisant le block n'a rien à  savoir et donc à  gérer pour te permettre d'avoir les informations contextuelles que tu cherches...

    C'est justement pour éviter d'avoir à  gérer la mémoire des objets de context que les blocks ont été conçu, dans certains callbacks en C-pure la structure de construction du callback te demande de donner des pointeurs de fonctions permettant à  l'implémenteur de faire des retains et des releases sur les contextInfo afin que ton propre code ne supprime pas ces données dans ton code, car le principe d'un callback c'est quand même d'être appelable à  un moment lointain et non-prévisible et très souvent le context d'exécution lors de la création du callback, n'existe plus, il faut donc que l'implémenteur conserve ces infos pour éviter de tout perdre.

    Les blocks d'Apple permettent de se simplifier la vie à  un point inimaginable sur ce genre de code... Et donc je tiens à  préciser que les blocks peuvent servir pour itérer, ce que je dis depuis le début, mais aussi pour trier, filtrer ou comme callback tout simple. Tout ça avec un minimum de gestion de ressources annexes (en tout cas seulement du côté de l'utilisateur, et pas de l'implémenteur qui n'en a plus rien à  battre) et un maximum de flexibilité.

    dans 1229001340:
    Enfin... En général à  partir du moment où on commence à  avoir besoin de pinailler sur la vitesse d'itération, il vaut mieux passer à  un autre langage que l'Objective-C je pense.


    L'Objective-C est très puissant et très pratique, dans la majorité des cas, l'exécution d'un code ObjC sera tout aussi rapide qu'un code C++, là  où ça ne sera pas le cas c'est justement lors des boucles très lourdes où l'optimisation est nécessaire, où chaque économie de messages et augmente la vitesse d'exécution de façon spéctaculaire, c'est dans ce genre de cas que tu vas avoir besoin de ce genre d'outils.

    Tu n'es pas à  la recherche de la moindre économie de cycle processeur, car souvent l'utilisateur ne fera pas la différence, là  où il fera la différence en revanche c'est quand tu vas par exemple comparer deux images, comparer deux tableaux, récupérer une liste de dossier et les traiter un par un, le calcule d'une image à  afficher à  l'écran dans un jeu vidéo par exemple, tous ces processus nécessitent des boucles très rapide et très efficace ; c'est là  que tu vas avoir besoin de ces outils pour prendre le moins de temps possible, c'est là  où ObjC montre ses faiblesses, et en tant que fan d'Object/Cocoa, je suis à  fond pour tout ce qui peut supprimer les rares faiblesses de ce langage/framework. ;)
  • AliGatorAliGator Membre, Modérateur
    06:24 modifié #38
    dans 1228996368:

    Le concept " objet " ne doit pas introduire de la rigidité, mais au contraire de la souplesse  ;)
    Ben c'est le cas des @property ^^
    C'est flexible dans le sens où :
    - Tu mets les attributs que tu veux pour ta propriété (retain, copy ou assign, nonatomic, etc.), ça ne se limite pas à  un type particulier d'accesseur quoi
    - Tu peux l'utiliser ou pas, si tu veux garder le fonctionnement précédent rien ne t'en empêche
    - Tu peux utiliser @synthetize si tu veux qu'il fasse tout tout seul, mais tu peux aussi définir tes propres setters et/ou getters pour ta variable/propriété, donc là  encore tu as toute la souplesse qu'il est possible d'avoir ;)
  • psychoh13psychoh13 Mothership Developer Membre
    06:24 modifié #39
    Selon moi, Objective-C/Cocoa est PRESQUE parfait, les blocks le rapproche encore plus de la perfection ! Mais peut-être qu'Apple trouvera encore de nouveaux outils pour le rendre encore plus parfait. ;)
  • schlumschlum Membre
    06:24 modifié #40
    dans 1229002461:

    En effet tu pourrais faire un callback type objet, mais question optimisation ce n'est pas pratique, et surtout, tu vas t'amuser à  créer une classe spécifique pour chaque context de ton application ? Non, je ne crois pas...


    Comment penses-tu qu'ont fait les générations de programmeurs C++ avant les closures ?  ;) (et qu'ils vont continuer à  faire à  partir du moment où il y a un besoin de portabilité avec Visual Studio par exemple...).
    La callback objet est définie en tant qu'une classe purement virtuelle qu'on spécialise au moment où on en a besoin...

    C'est justement pour éviter d'avoir à  gérer la mémoire des objets de context que les blocks ont été conçu, dans certains callbacks en C-pure la structure de construction du callback te demande de donner des pointeurs de fonctions permettant à  l'implémenteur de faire des retains et des releases sur les contextInfo afin que ton propre code ne supprime pas ces données dans ton code, car le principe d'un callback c'est quand même d'être appelable à  un moment lointain et non-prévisible et très souvent le context d'exécution lors de la création du callback, n'existe plus, il faut donc que l'implémenteur conserve ces infos pour éviter de tout perdre.


    Houlà ... une callback est toujours appelée dans le contexte d'exécution... c'est quoi cette histoire de " moment lointain " ?

    Les blocks d'Apple permettent de se simplifier la vie à  un point inimaginable sur ce genre de code... Et donc je tiens à  préciser que les blocks peuvent servir pour itérer, ce que je dis depuis le début, mais aussi pour trier, filtrer ou comme callback tout simple. Tout ça avec un minimum de gestion de ressources annexes (en tout cas seulement du côté de l'utilisateur, et pas de l'implémenteur qui n'en a plus rien à  battre) et un maximum de flexibilité.


    Certes, ça peut être bien pratique comme simplification syntaxique, mais c'est pas non plus une révolution  :P

    L'Objective-C est très puissant et très pratique, dans la majorité des cas, l'exécution d'un code ObjC sera tout aussi rapide qu'un code C++, là  où ça ne sera pas le cas c'est justement lors des boucles très lourdes où l'optimisation est nécessaire, où chaque économie de messages et augmente la vitesse d'exécution de façon spéctaculaire, c'est dans ce genre de cas que tu vas avoir besoin de ce genre d'outils.


    Ce n'est pas le cas à  partir du moment où il y a beaucoup d'appels de sélecteurs (entre autre, récursion). Car un appel de sélecteur est beaucoup moins performant qu'un appel de fonction.

    Tu n'es pas à  la recherche de la moindre économie de cycle processeur, car souvent l'utilisateur ne fera pas la différence, là  où il fera la différence en revanche c'est quand tu vas par exemple comparer deux images, comparer deux tableaux, récupérer une liste de dossier et les traiter un par un, le calcule d'une image à  afficher à  l'écran dans un jeu vidéo par exemple, tous ces processus nécessitent des boucles très rapide et très efficace ; c'est là  que tu vas avoir besoin de ces outils pour prendre le moins de temps possible, c'est là  où ObjC montre ses faiblesses, et en tant que fan d'Object/Cocoa, je suis à  fond pour tout ce qui peut supprimer les rares faiblesses de ce langage/framework. ;)


    C'est un langage / framework d'interface. Nullement fait pour faire ce genre de gros traitements !
    Il n'est pas encore là  le jour où on programmera un moteur de jeu vidéo ou de logiciel sérieux de traitement de données en Objective-C...
  • AliGatorAliGator Membre, Modérateur
    06:24 modifié #41
    dans 1229004011:

    Il n'est pas encore là  le jour où on programmera un moteur de jeu vidéo ou de logiciel sérieux de traitement de données en Objective-C...
    D'autant que ce langage n'est pas fait pour ça non plus, pour tout ce qui est gros algos nécessitant une optimisation, faut mieux faire ça en C qu'en Objective-C ;)

    J'aime bien Objective-C et Objective-C 2.0, je trouve qu'il y a clairement des concepts très intéressants dans le langage comme dans le framework Cocoa, après comme tout langage et comme tout framework, il n'est pas parfait !
    Le fait d'être obligé de tout créer dynamiquement et de ne pas avoir la possibilité de créer des objets sur la pile comme en C++ par exemple c'est dommage. Et le fait que du coup le langage étant entièrement dynamique, certes ça offre des avantages, mais côté tests ça peut plus facilement planter au runtime au lieu de faire des erreurs de compilation comme en C++ par exemple (certaines erreurs apparaà®traient en C++ lors de la compilation et n'apparaà®ssent qu'au runtime en Objective-C, alors si c'est dans un cas d'un if dans lequel on ne passe pas souvent, ça met pas l'erreur en valeur ;)

    Voilà , je suis plutôt fan d'Objective-C par rapport à  certains autres langages c'est vrai, mais faut savoir aussi admettre qu'il a des défauts :D
  • psychoh13psychoh13 Mothership Developer Membre
    06:24 modifié #42
    dans 1229004011:
    Comment penses-tu qu'ont fait les générations de programmeurs C++ avant les closures ?  ;) (et qu'ils vont continuer à  faire à  partir du moment où il y a un besoin de portabilité avec Visual Studio par exemple...).
    La callback objet est définie en tant qu'une classe purement virtuelle qu'on spécialise au moment où on en a besoin...


    Bah justement... C++ pour moi est un langage à  chier, inutilement compliqué qui ajoute plein de fonctionnalités inutiles dans d'autres langages qui alourdissent la lecture du code et qui sont collés les unes aux autres sans cohérence apparente... Pour moi l'exemple du C++ c'est justement quelque chose à  éviter, et c'est pour ça que les langages évoluent pour supprimer les défauts du passé... Il se trouve que PHP et C++ le font très très mal, rendant ces deux langages, pour moi, exécrable.

    dans 1229004011:
    Houlà ... une callback est toujours appelée dans le contexte d'exécution... c'est quoi cette histoire de " moment lointain " ?


    Justement non, la plupart des callbacks se passent dans des context différent, par exemple, un NSStream qui utilise un delegate, il va dire au delegate qu'il a reçu des données, ça peut se passer bien après que la méthode ayant générée le NSStream disparaisse...
    De même, pour les CGShading, la fonction permettant le calcul des couleurs à  afficher en un point donné, et qu'on doit passer à  la fonction de construction du shading est aussi appelée bien après que le contexte d'exécution dans lequel le shading a été créé disparaisse.

    Bien au contraire, mon cher (merci pour la rime), les callbacks sont justement faits pour récupérer des données, et permettre l'exécution de certains codes à  des moments imprévisibles et surtout bien souvent hors du context d'exécution.

    dans 1229004011:
    Certes, ça peut être bien pratique comme simplification syntaxique, mais c'est pas non plus une révolution  :P

    Moi sincèrement je pense que si.

    dans 1229004011:
    Ce n'est pas le cas à  partir du moment où il y a beaucoup d'appels de sélecteurs (entre autre, récursion). Car un appel de sélecteur est beaucoup moins performant qu'un appel de fonction.


    Justement, un block est aussi rapide qu'un appel de fonctions, et en plus il conserve le contexte d'exécution, il est fait pour ce genre de cas où les performances sont une nécessité.

    dans 1229005361:

    dans 1229004011:

    Il n'est pas encore là  le jour où on programmera un moteur de jeu vidéo ou de logiciel sérieux de traitement de données en Objective-C...
    D'autant que ce langage n'est pas fait pour ça non plus, pour tout ce qui est gros algos nécessitant une optimisation, faut mieux faire ça en C qu'en Objective-C ;)


    Justement, c'est là  que vous n'avez pas compris la philosophie d'Objective-C, vous croyiez qu'Objective-C a été conçu à  partir du C et gardé 100% compatible avec le C juste pour faire plaisir aux développeurs C ?

    Certes, la compatibilité avec le C voulu dès l'origine était là  pour profiter de toutes les bibliothèques déjà  disponibles en C sans avoir à  retaper une seule ligne de code. Mais aussi et surtout, le fait d'être 100% compatible avec le C, et je dirais même d'être un sur-ensemble du C, ça permet d'avoir pour la plupart des tâches un langage objet très pratique et puissant, et pour les tâches lourdes du C pur. Si vous avez besoin de traitement lourd, vous faites tout le code lourd en C pur, et avec une seule méthode, vous appelez cette fonction. Une fois dans la méthode, l'exécution est aussi rapide en C qu'en Objective-C, ce qui est lourd, c'est pas la méthode elle-même, c'est la récupération du pointeur de cette méthode.

    Par exemple, je me suis amusé à  concevoir un programme qui affiche une fractale tout en Objective-C/Cocoa et dont la forme est définie par la position du pointeur de la souris, et pour faire classe, je capte le déplacement du pointeur sans avoir à  appuyer sur aucune touche, vous allez me dire ça doit ramer... Et bien pas du tout, c'est extrêmement fluide, ça utilise une CIImage pour l'affiche, NSData pour stocker la valeur de chaque pixel à  dessiner, et le calcule des couleurs de chaque pixels se fait dans une fonction C contenant 3 boucles imbriquées... Et cette application est aussi rapide voire même plus rapide que la même en utilisant SDL et du C pur...

    dans 1229005361:
    Voilà , je suis plutôt fan d'Objective-C par rapport à  certains autres langages c'est vrai, mais faut savoir aussi admettre qu'il a des défauts :D


    Objective-C a des défauts, oui, c'est pour ça qu'il n'est pas parfait... C'est sûr que j'aimerais bien qu'il y ait une syntaxe ou une façon FACILITANT les comportements statiques. On peut faire de l'ObjC tout statiquement, mais c'est pas facilité par le langage, et surtout dans la majorité des cas ce n'est pas utile.

    Objective-C est fait pour tout faire, et pour ça il faut savoir l'exploiter au mieux : j'ai besoin d'une interface objet, j'utilise les classes et méthodes ObjC, j'ai besoin de faire des traitements lourds j'utilise la partie procédurale. Il n'y a rien qu'Objective-C ne puisse faire, pas plus que Cocoa et tous les frameworks d'Apple qui l'entourent, la seule chose qui peut limiter ObjC/Cocoa c'est la frilosité des développeurs !
  • AliGatorAliGator Membre, Modérateur
    06:24 modifié #43
    dans 1229008608:

    ça permet d'avoir pour la plupart des tâches un langage objet très pratique et puissant, et pour les tâches lourdes du C pur.
    Ben heu c'est ce qu'on a dit, non ? Pour la partie IHM de l'objet, en l'occurence en Objective-C, et pour la partie algo du C pur...
  • schlumschlum Membre
    06:24 modifié #44
    dans 1229008608:

    Bah justement... C++ pour moi est un langage à  chier, inutilement compliqué qui ajoute plein de fonctionnalités inutiles dans d'autres langages qui alourdissent la lecture du code et qui sont collés les unes aux autres sans cohérence apparente... Pour moi l'exemple du C++ c'est justement quelque chose à  éviter, et c'est pour ça que les langages évoluent pour supprimer les défauts du passé... Il se trouve que PHP et C++ le font très très mal, rendant ces deux langages, pour moi, exécrable.


    Peut-être, mais le C++ a niveau performances un avantage énorme par rapport à  l'Objective-C : il sait travailler en objets sur la pile.
    Ce qui permet de faire un minimum d'allocations et une gestion extrêmement propre et rapide de la mémoire.
    Le système d'exceptions est également plus puissant que celui d'Objective-C, car tous les destructeurs des objets de la pile sont appelés d'office (à  noter quand même l'effort de l'Objective-C avec les NSAutoReleasePool qui fonctionnent de la même manière, et que je soupçonne d'être des objets sur la pile du coup ; ce qui expliquerait la nécessité de les créer et les détruire dans le même contexte :P)
    Et il permet également d'avoir des variables de classe, ce qu'on ne peut faire proprement en Objective-C...
    Quant aux fonctionnalités inutiles, il suffit de ne pas les utiliser...

    Les grands avantages de l'Objective-C / Cocoa sur le C++ étant la gestion de la mémoire, avec le NSAutoReleasePool qui évite bien des tracas et des callbacks déjà . Plus dans une moindre mesure, sa flexibilité qui déporte certains choix de la compilation au runtime.

    Justement non, la plupart des callbacks se passent dans des context différent, par exemple, un NSStream qui utilise un delegate, il va dire au delegate qu'il a reçu des données, ça peut se passer bien après que la méthode ayant générée le NSStream disparaisse...
    De même, pour les CGShading, la fonction permettant le calcul des couleurs à  afficher en un point donné, et qu'on doit passer à  la fonction de construction du shading est aussi appelée bien après que le contexte d'exécution dans lequel le shading a été créé disparaisse.

    Bien au contraire, mon cher (merci pour la rime), les callbacks sont justement faits pour récupérer des données, et permettre l'exécution de certains codes à  des moments imprévisibles et surtout bien souvent hors du context d'exécution.


    Ah mais là  mon cher, tu dépasses le problème de callbacks pour parler de contextes  ;) Effectivement, les objets dont tu parles ont besoin d'un contexte de travail, et c'est à  cause du contexte et non d'une callback qu'il faut faire attention ! (le contexte devant survivre parfois plusieurs cycles de runloop).
    Dans le fonctionnement callback standard, une fonction A fait appel dans son scope à  une fonction B avec une fonction C en callback ; C est utilisée durant l'exécution de B, puis B se termine (toujours dans le scope de A), et la callback a fait son office.
    Dans le fonctionnement d'un contexte, c'est plus compliqué effectivement, il faut allouer le contexte, le passer, et que sa destruction soit gérée quand on n'en a plus besoin...

    Par exemple, je me suis amusé à  concevoir un programme qui affiche une fractale tout en Objective-C/Cocoa et dont la forme est définie par la position du pointeur de la souris, et pour faire classe, je capte le déplacement du pointeur sans avoir à  appuyer sur aucune touche, vous allez me dire ça doit ramer... Et bien pas du tout, c'est extrêmement fluide, ça utilise une CIImage pour l'affiche, NSData pour stocker la valeur de chaque pixel à  dessiner, et le calcule des couleurs de chaque pixels se fait dans une fonction C contenant 3 boucles imbriquées... Et cette application est aussi rapide voire même plus rapide que la même en utilisant SDL et du C pur...


    C'est normal, c'est la même... Derrière CI il y a des appels GL au GPU.
    Il ne faut pas se leurrer... Les objets de Foundation sont pour la plupart de beaux wrappers objets autour des bibliothèques C de CoreFoundation ou des bibliothèques C standard ou des bibliothèques C BSD.
    Mais ce bel emballage avec ses appels dynamiques et allocations multiples ralentit toute la machinerie ; c'est très bien pour l'interface, mais pour faire un vrai moteur non.

    Après, si on part du principe que de toute manière le C c'est de l'Objective-C et le C++ c'est de l'Objective-C++, alors oui, y a plein de moteurs faits en Objective-C !  ;D
  • MalaMala Membre, Modérateur
    06:24 modifié #45
    Je commence à  lire du début et je reviens... ...dans deux jours.  :)
  • AliGatorAliGator Membre, Modérateur
    06:24 modifié #46
    dans 1229014631:

    Je commence à  lire du début et je reviens... ...dans deux jours.  :)
    Wah tu lis... vite :)
  • CéroceCéroce Membre, Modérateur
    06:24 modifié #47
    Bon je vais mettre tout le monde d'accord (pour me jeter des pierres).

    Quand on programme un peu en Python, par exemple, on se rend compte à  quel point ObjC est vieillot. Dans ce langage, on passe son temps à  déclarer des trucs. On veut une liste: il faut créer un NSMutableArray. On veut les objets aux index 5 à  18 ? Il faut aller chercher dans la doc comment s'appelle cette foutue méthode (subarrayWithItemsInRange:NSMakeRange(5,13-1) ?).

    Alors oui, la différence, c'est qu'ObjC est plus rapide que Python, et c'est un compromis. Il n'empêche que les derniers ajouts: propriétés et boucle for...in, sont bien des tentatives de se rapprocher des langages de plus haut niveau. Et je trouve que c'est une bonne chose:

    Avant:
    NSArray* pages = [documents pages];<br />NSEnumerator* pagesEnum = [pages objectEnumerator];<br />CePage* page;<br />while(page = [pagesEnum nextObject])<br />{<br />&nbsp;  blablabla...<br />}
    


    Après:
    NSArray* pages = [documents pages];<br />for(CePage* page in pages)<br />{<br />&nbsp;  blablabla...<br />}
    


    Et ben, c'est moins chiant à  taper et plus lisible. Après, si c'est plus rapide, tant mieux.
    (En plus XCode peut transformer automatiquement les vieilles énumérations en nouvelles).


    Pour l'accès aux propriétés: ouais, avoir utilisé le . , c'est pas très malin, ils auraient pu utiliser : ou @, ou #, mais c'est quand même plus lisible, et moins chiant à  taper que des appels de méthodes imbriqués (où on met des ] jusqu'à  ce que XCode affiche que le compte est bon).

    Pour les propriétés:

    Avant:
    - (NSColor*) color;<br />- (void) setColor:(NSColor*) theColor;<br /><br />- (NSColor*) color<br />{<br />&nbsp;  return color;<br />}<br /><br />- (void) setColor:(NSColor*) theColor<br />{<br />&nbsp;  if(color)<br />&nbsp; &nbsp; &nbsp; [color release];<br /><br />&nbsp;  color = [theColor retain];<br />}
    



    Après:
    @property (retain) NSColor* color;<br /><br />@synthesize color;
    


    J'aime beaucoup les propriétés ! Certes, une fois le modèle défini, on n'y touche plus, mais je préfère passer du temps sur du code un peu moins bête.



    Ben finalement, j'ai pas mis tout le monde d'accord, et c'est bien dommage, c'est pas drôle les débats où il n'y a qu'un détracteur.





  • denis_13denis_13 Membre
    06:24 modifié #48
    Bonjour à  tous,
    juste pour relancer le débat, vous devriez lire cette page très intéressante:
    http://camaelon.blogspot.com/2007/01/fun-with-objective-c.html

    Bonne soirée

    Denis
  • psychoh13psychoh13 Mothership Developer Membre
    06:24 modifié #49
    dans 1229014102:

    Peut-être, mais le C++ a niveau performances un avantage énorme par rapport à  l'Objective-C : il sait travailler en objets sur la pile.
    Ce qui permet de faire un minimum d'allocations et une gestion extrêmement propre et rapide de la mémoire.

    Je sais pas c'est réellement un avantage, pour avoir la même chose sans problème tu as le garbage collector, c'est pas vraiment pour rien que la plupart des langages objets utilises l'allocation dynamique pour les objets, je sais que le Java et C# ne sont pas géniaux, mais je peux vous dire que je les préfère largement au C++. :D


    dans 1229014102:
    Le système d'exceptions est également plus puissant que celui d'Objective-C, car tous les destructeurs des objets de la pile sont appelés d'office (à  noter quand même l'effort de l'Objective-C avec les NSAutoReleasePool qui fonctionnent de la même manière, et que je soupçonne d'être des objets sur la pile du coup ; ce qui expliquerait la nécessité de les créer et les détruire dans le même contexte :P)

    Le système d'exception n'est pas forcément mieux, déjà  il n'a pas de close finally qui permet d'exécuter un bout de code qu'il y ait une exception ou pas... De toutes façons, les exceptions doivent rester exceptionnelles (comme l'indique leur nom) et moins tu en as mieux c'est.

    Les autorelease pools de leur côté sont comme tous les objets ObjC alloué dynamiquement dans le tas, elles sont conçues sous forme de pile, c'est-à -dire que tous les objets autoreleasé à  un moment donné iront dans la dernière pool allouée, une fois que cette pool est supprimée, les objets iront dans la pool en-dessus.
    Mais le truc c'est qu'il y a une pile d'autorelease pool par thread, donc tu dois toujours alloué et supprimé une pool dans le même thread en revanche tu te fiches de savoir si c'est dans la même méthode ou pas.


    dans 1229014102:
    Et il permet également d'avoir des variables de classe, ce qu'on ne peut faire proprement en Objective-C...
    Quant aux fonctionnalités inutiles, il suffit de ne pas les utiliser...

    Les variables de classe devaient être implémenter en ObjC, parmi les fonctions du runtime tu en vois prévues à  cette effet, mais ils n'ont sans doute pas eu le temps de finir de les implémenter et donc pour l'instant c'est en suspend ; sinon côté propreté, je m'excuse mais le système actuel n'est pas plus mauvais qu'un autre, enfin bon... C'est pas le genre de trucs qu'on utilise souvent.

    dans 1229014102:
    Ah mais là  mon cher, tu dépasses le problème de callbacks pour parler de contextes  ;) Effectivement, les objets dont tu parles ont besoin d'un contexte de travail, et c'est à  cause du contexte et non d'une callback qu'il faut faire attention ! (le contexte devant survivre parfois plusieurs cycles de runloop).
    Dans le fonctionnement callback standard, une fonction A fait appel dans son scope à  une fonction B avec une fonction C en callback ; C est utilisée durant l'exécution de B, puis B se termine (toujours dans le scope de A), et la callback a fait son office.
    Dans le fonctionnement d'un contexte, c'est plus compliqué effectivement, il faut allouer le contexte, le passer, et que sa destruction soit gérée quand on n'en a plus besoin...


    Dans les deux cas ça s'appelle un callback, et le fait d'appeler ça un callback n'implique en rien que les fonctions doivent être exécuter dans la même portée que la fonction originelle, bien au contraire...
    D'ailleurs, le callback, en C standard en tout cas, est forcément une fonction externe à  la fonction appelante, et donc, elle n'est pas dans la même portée (scope) que la fonction appelante ou même la fonction appelée, que ce soit une fonction exécutée pendant l'exécution de la fonction appelante, ou après la fin de cette dernière, dans les deux cas, aucune des trois fonctions (appelante, appelée et callback) n'a accès à  la portée de l'une des 3 autres.

    Dans le cas des closures, qui peuvent s'apparenter aux fonctions imbriquées de GNU-C99, le block a accès à  tout le contenu de la fonction appelante, et après la mort de la fonction appelante, le block peut encore vivre, ce qui n'est pas le cas d'une fonction imbriquée.

    dans 1229014102:
    C'est normal, c'est la même... Derrière CI il y a des appels GL au GPU.
    Il ne faut pas se leurrer... Les objets de Foundation sont pour la plupart de beaux wrappers objets autour des bibliothèques C de CoreFoundation ou des bibliothèques C standard ou des bibliothèques C BSD.
    Mais ce bel emballage avec ses appels dynamiques et allocations multiples ralentit toute la machinerie ; c'est très bien pour l'interface, mais pour faire un vrai moteur non.

    Après, si on part du principe que de toute manière le C c'est de l'Objective-C et le C++ c'est de l'Objective-C++, alors oui, y a plein de moteurs faits en Objective-C !  ;D


    Et bien oui, tu rigoles, mais c'est justement là  où je veux en venir, j'ai déjà  lu plein de fois des gens qui prétendaient que Objective-C/Cocoa n'étaient pas fait pour faire des jeux vidéos, parce que le runtime est trop lent, parce que c'est trop bordélique, etc.

    Mais c'est totalement faux ! On peut très bien faire des jeux en ObjC il n'y a aucun problème, l'ObjC sans le C ce n'est rien du tout, 90% d'Objective-C c'est du C pur, je ne me leurre pas du tout, c'est un fait, l'Objective-C, c'est du C, point bar. Donc, à  partir de là , tout est possible.

    J'aimerais bien savoir comment tu peux afficher quoique ce soit à  l'écran sans utiliser un GPU... Je rappelle qu'Objective-C n'est qu'un langage, il n'y a pas de notion de graphisme ou de console dans un langage.
  • schlumschlum Membre
    06:24 modifié #50
    dans 1229023815:

    dans 1229014102:

    Peut-être, mais le C++ a niveau performances un avantage énorme par rapport à  l'Objective-C : il sait travailler en objets sur la pile.
    Ce qui permet de faire un minimum d'allocations et une gestion extrêmement propre et rapide de la mémoire.

    Je sais pas c'est réellement un avantage, pour avoir la même chose sans problème tu as le garbage collector, c'est pas vraiment pour rien que la plupart des langages objets utilises l'allocation dynamique pour les objets, je sais que le Java et C# ne sont pas géniaux, mais je peux vous dire que je les préfère largement au C++. :D


    C'est dingue, on dirait moi au même âge  :)
    À cracher toute ma bile sur le C++... Jusqu'au jour où j'ai vraiment dû bosser avec chez les éditeurs & industries.
    C'est un langage qui s'apprivoise  :o

    Le Java par contre, jamais pu...  ::)
  • schlumschlum Membre
    06:24 modifié #51
    dans 1229023815:

    dans 1229014102:
    Le système d'exceptions est également plus puissant que celui d'Objective-C, car tous les destructeurs des objets de la pile sont appelés d'office (à  noter quand même l'effort de l'Objective-C avec les NSAutoReleasePool qui fonctionnent de la même manière, et que je soupçonne d'être des objets sur la pile du coup ; ce qui expliquerait la nécessité de les créer et les détruire dans le même contexte :P)

    Le système d'exception n'est pas forcément mieux, déjà  il n'a pas de close finally qui permet d'exécuter un bout de code qu'il y ait une exception ou pas... De toutes façons, les exceptions doivent rester exceptionnelles (comme l'indique leur nom) et moins tu en as mieux c'est.


    Les exceptions, c'est le traitement d'erreur des langages objets... Il y en a partout  ;D
    Même dans ton Framework chéri il y en a des tonnes... Quand on file un mauvais index pour un array, quand il y a une erreur de désarchivage, un message à  un sélecteur qui n'existe pas etc. Toutes les erreurs sont traitées par exceptions ; le temps des codes de retour d'erreur à  la C est révolu  :P
  • schlumschlum Membre
    06:24 modifié #52
    dans 1229023815:

    Les autorelease pools de leur côté sont comme tous les objets ObjC alloué dynamiquement dans le tas, elles sont conçues sous forme de pile, c'est-à -dire que tous les objets autoreleasé à  un moment donné iront dans la dernière pool allouée, une fois que cette pool est supprimée, les objets iront dans la pool en-dessus.
    Mais le truc c'est qu'il y a une pile d'autorelease pool par thread, donc tu dois toujours alloué et supprimé une pool dans le même thread en revanche tu te fiches de savoir si c'est dans la même méthode ou pas.


    Ah non, regarde la doc :
    You should always drain an autorelease pool in the same context (invocation of a method or function, or body of a loop) that it was created. See Autorelease Pools for more details and several code samples using autorelease pools.


    C'est pour ça que je dis qu'il y a anguille sous roche quant à  l'implémentation... AMHA c'est pas de l'allocation dynamique en " pile " comme tu dis.
    Le scope a l'air d'avoir une importance capitale, comme pour les objets C++ déclarés sur la pile, curieusement...
  • schlumschlum Membre
    06:24 modifié #53
    dans 1229021690:

    Bonjour à  tous,
    juste pour relancer le débat, vous devriez lire cette page très intéressante:
    http://camaelon.blogspot.com/2007/01/fun-with-objective-c.html

    Bonne soirée

    Denis


    C'est un bench intéressant, et ça montre bien à  quel point les objets et appels Obj-C sont lents !
    Quant aux bidouilles pour avoir des objets optimisés sur la pile, OMG, c'est atroce à  lire :)
  • psychoh13psychoh13 Mothership Developer Membre
    décembre 2008 modifié #54
    dans 1229025444:
    C'est dingue, on dirait moi au même âge  :)
    À cracher toute ma bile sur le C++... Jusqu'au jour où j'ai vraiment dû bosser avec chez les éditeurs & industries.
    C'est un langage qui s'apprivoise  :o

    Le Java par contre, jamais pu...  ::)


    Bah personnellement, je supporte mieux le java que le C++, mais je préfère le C# au java, le seul problème de C# c'est qu'il n'existe vraiment que dans .NET et ça je peux pas non plus supporter.

    Je suis tout à  fait capable de supporter C++, de coder en C++, etc. Si un jour dans mon boulot je dois obligatoire coder en C++, je ferai bien sûr tout pour qu'il me pourrisse pas trop la vie, mais tu ne me verras jamais défendre ce langage... Je le mets dans le même panier que PHP en langage web, j'en fais au boulot ça m'aide pas plus à  le supporter.

    dans 1229025653:
    Les exceptions, c'est le traitement d'erreur des langages objets... Il y en a partout  ;D
    Même dans ton Framework chéri il y en a des tonnes... Quand on file un mauvais index pour un array, quand il y a une erreur de désarchivage, un message à  un sélecteur qui n'existe pas etc. Toutes les erreurs sont traitées par exceptions ; le temps des codes de retour d'erreur à  la C est révolu  :P


    J'ai jamais dit qu'il n'existait pas d'exception en ObjC/Cocoa, j'ai dit que cela devait rester exceptionnel, en utiliser le moins possible c'est-à -dire éviter de faire jeter des exceptions par les méthodes du framework, il faut toujours vérifier que tu n'utilises pas un index plus grand que la taille de l'array, c'est évident, si tu ne fais pas ça tu es un idiot. D'ailleurs la doc d'Apple stipule clairement que les exceptions ne doivent être utilisées que dans le cadre de vraies problèmes lier au code et doivent être réservées à  la seule utilisation du développeur, et sinon pour la gestion d'erreur il vaut mieux utiliser NSError, qui ressemble beaucoup au système des codes retour du C...

    dans 1229025898:
    Ah non, regarde la doc :
    You should always drain an autorelease pool in the same context (invocation of a method or function, or body of a loop) that it was created. See Autorelease Pools for more details and several code samples using autorelease pools.


    C'est pour ça que je dis qu'il y a anguille sous roche quant à  l'implémentation... AMHA c'est pas de l'allocation dynamique en " pile " comme tu dis.
    Le scope a l'air d'avoir une importance capitale, comme pour les objets C++ déclarés sur la pile, curieusement...


    Je n'ai pas dit que c'était de l'allocation en pile, j'ai dit que le fonctionnement des autorelease pools se faisait sous forme de pile, c'est-à -dire LIFO ou DAPS "Dernier arrivé premier sorti", c'est-à -dire que tu vas avoir une pool de départ dans lequel les premiers objets iront, ensuite une nouvelle pool sera allouée et "masquera" la première pool, tous les objets à  partir de ce moment iront dans la nouvelle, puis un nouvelle pool arrivera et masquera la précédente, puis cette dernière sera supprimé et tous les objets dont elle a la charger aussi, et à  nouveau les objets iront dans la deuxième pool, puis celle-ci sera supprimé et tous les objets iront dans la première, et avant que le programme ne soit terminé, celle-ci sera aussi supprimé et les objets dont elle a la charge aussi, etc.
    ça c'est un comportement décrit dans la documentation des autoreleases pool

    Ensuite, si tu es obligé de supprimer la pool dans le même contexte, c'est tout à  fait normal, je m'excuse pour t'avoir embrouillé plus tôt : l'explication est très simple, quand tu utilises l'AppKit, celui-ci va te créer régulièrement des autorelease pools, à  chaque boucle d'événement pour permettre la suppression régulière des objets autoreleasés...

    Donc avant l'appel de la méthode A, l'AppKit crée la pool P1, dans la méthode A, tu crées la pool P2, qui va donc masquer la pool P1, tu vas y mettre les objets autoreleasés, une fois la méthode A terminée, l'AppKit va supprimée la pool P1, le problème vient de là , c'est que la pool P2 existe toujours, et comme les pools sont construites sous forme de piles ça fait boguer parce qu'on enlève un élément intermédiaire alors qu'on ne peut ajouter ou enlever des éléments qu'au plus haut de la pile.

    Voilà  pourquoi on doit supprimer une autorelease pool dans le même contexte, ou du moins surtout dans le cas de AppKit.

    Pour ce qui est de cette exigence ce n'est donc pas parce que les objets sont alloués sur la pile d'exécution, mais bien parce que ces objets fonctionnent entre eux sous forme de pile, ensuite, le système d'exception permet de nettoyer proprement les autorelease pools tout simplement parce que dans l'une des méthodes d'envoi d'exception, il y a sans doute la méthode supprimant la pool en cours d'utilisation.
    dans 1229027659:
    C'est un bench intéressant, et ça montre bien à  quel point les objets et appels Obj-C sont lents !
    Quant aux bidouilles pour avoir des objets optimisés sur la pile, OMG, c'est atroce à  lire :)


    Personnellement, je préfère montrer ce benchmark : http://www.mikeash.com/?page=pyblog/performance-comparisons-of-common-operations-leopard-edition.html qui représente bien mieux la toute relative lenteur d'Objective-C...

    Mais bon rappelons-nous aussi que Leopard a du être fini à  la va-vite pour essayer de respecter les délais, il suffit de regarder les sources du runtime d'Objective-C pour s'en rendre compte, le nombre de FIXME qui s'y trouvent est impressionnant, mais m'est avis que Snow Leopard va corriger tout ça.

    PS: si je fais autant confiance à  Apple c'est qu'ils sont capables de faire des trucs très impressionnant, exemple : http://ridiculousfish.com/blog/archives/2005/12/23/array/ .
  • schlumschlum Membre
    06:24 modifié #55
    Bien sûr que les exceptions doivent rester exceptionnelles en utilisation normale... ça n'empêche qu'elles arrivent et qu'on en peut pas toujours les " prévenir "...
    Un exemple qui me vient à  l'esprit :
    NSKeyedUnarchiver *unarch = nil;<br />@try {<br />	unarch = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];<br />}<br />@catch(NSException *error) {<br />	// ... Error management<br />}
    


    On ne peut prévoir à  l'avance si l'objet data est bien formé et ne va pas faire péter une exception à  NSKeyedUnarchiver...
  • schlumschlum Membre
    06:24 modifié #56
    Sinon, SnowLeopard, c'est bien beau... mais c'est pas magique non plus  :P
    Ils ne vont pas inventer la poudre à  faire aller un appel de sélecteur aussi rapidement qu'un appel de fonction géré à  la compilation
    Ni le chapeau à  faire aller les allocations dynamiques aussi rapidement que les définitions sur la pile  ;)
  • ChachaChacha Membre
    06:24 modifié #57
    dans 1229029900:

    Ils ne vont pas inventer la poudre à  faire aller un appel de sélecteur aussi rapidement qu'un appel de fonction géré à  la compilation
    Ni le chapeau à  faire aller les allocations dynamiques aussi rapidement que les définitions sur la pile  ;)


    Ce n'est pas une solution miracle, mais c'est intéressant à  placer ici : les sélecteurs sont "lents" mais c'est surtout gênant dans un calcul intensif. Or, dans un calcul intensif, généralement on n'utilise pas 50000 sélecteurs différents, et on sait sur quels objets on travaille. Dans ce cas, le IMP caching peut être employé.
    En fait, n'importe quelle méthode n'est jamais qu'une fonction qui reçoit "self" en paramètre (entre autres), et le rôle du sélecteur est d'identifier cette fonction. Une telle fonction a un prototype IMP (cf objc-runtime.h). On peut donc faire la résolution une bonne fois pour toutes puis appeler directement la fonction : tant que c'est pour des objets de classe identique, c'est ok.

    +
    Chacha
  • AliGatorAliGator Membre, Modérateur
    décembre 2008 modifié #58
    Oui c'est expliqué dans la doc de NSObject au tout début (partie "Selectors") où ils disent qu'on peut pour optimiser récupérer le pointeur de fonction (de type IMP : [tt]typedef id (*IMP)(id, SEL, ...)[/tt]) correspondant à  un sélecteur et appeler cette fonction C directement (en lui passant self et le @selector en paramètre) pour accélérer les appels plutôt que d'appeler le selecteur à  chaque fois ce qui nécessite sa résolution par le runtime pour savoir quelle méthode appeler.

    Donc pour une grosse boucle qui appelle très souvent une certaine méthode, ça peut valoir le coup si on a besoin d'optimiser de passer par ces pointeurs de fonctions (IMP) et donc de retourner du côté C pur pour appeler les fonctions sur nos objets et non pas utiliser l'envoi de messages ;)

    Le lien "random thoughts of a cameleon" cité plus haut est intéressant sur ce point, il montre l'apport du method caching en effet... mais aussi comment créer des objets Objective-C sur la pile... Mais bon en même temps si on commence à  faire ça ça fait un peu bidouille et du code assez dur à  lire je trouve...
    typedef struct { @defs(MaClasse) }&nbsp; MaClasse_ONSTACK;<br />MaClasse_ONSTACK toto_ONSTACK;<br />toto_ONSTACK.isa = [MaClasse class];<br /><br />MaClasse* toto = (MaClasse*)&amp;toto_ONSTACK;
    
    Beeerk ça montre que c'est faisable si on veut déclarer une classe sur la pile (et ça semble optimiser un peu côté vitesse mais attention aux effets de bords possibles genre appel de dealloc) mais ça fait vraiment hack et illisible !
  • Philippe49Philippe49 Membre
    06:24 modifié #59
    dans 1229043857:

    Le lien "random thoughts of a cameleon" cité plus haut est intéressant sur ce point, il montre l'apport du method caching en effet... mais aussi comment créer des objets Objective-C sur la pile... Mais bon en même temps si on commence à  faire ça ça fait un peu bidouille et du code assez dur à  lire je trouve...
    typedef struct { @defs(MaClasse) }&nbsp; MaClasse_ONSTACK;<br />MaClasse_ONSTACK toto_ONSTACK;<br />toto_ONSTACK.isa = [MaClasse class];<br />
    


    En même temps, le dealloc ne marche pas sur ce type de structure ... cela voudrait dire qu'en fait ce qu'il propose c'est une structure C reprenant le modèle de l'objet Obj_C ?
    Il me semble donc comparer plus C++ à  C que C++ à  Obj-C. Ce que je me dis, c'est que si les concepteurs d'Obj-C n'ont pas pris l'option de ce type de structure, c'est qu'il y avait une bonne raison quelque part.
    Cela me conforte dans l'idée que pour faire des performances, Obj-C propose de le faire en C, et que pour faire de l'interface, il propose Obj-C . Obj-C répond a des besoins d'optimisation de qualité de l'interfaçage, et non du temps d'exécutions : Qui va créer 10000000 NSTextView ?
    Mais je retiens que des discussions dans des posts précédents tendaient à  montrer qu'Obj-C progresse dans la part optimisation de code.   

    Quand à  "thoughts of Cameleon", on ne voit pas le code sur lequel il compare ObjC et C++. Tout cela ne me semble pas très scientifique, et dans ce genre d'études de cas particuliers, tout et son contraire peut être dit. 
  • psychoh13psychoh13 Mothership Developer Membre
    06:24 modifié #60
    typedef struct { @defs(MaClasse) }&nbsp; MaClasse_ONSTACK;<br />MaClasse_ONSTACK toto_ONSTACK;<br />toto_ONSTACK.isa = [MaClasse class];<br /><br />MaClasse* toto = (MaClasse*)&amp;toto_ONSTACK;
    


    Ce code n'est plus utilisable dans ObjC 2. La directive @defs() permet de donner à  une structure les même membre que la classe en paramètre. Le problème c'est qu'il faut avoir la définition d'une classe concrète, ça ne peut donc pas marcher avec les class-clusters (NSString, NSArray, NSDictionary...) qui sont des classes abstraites qui allouent des instances de leurs sous-classes concrètes.
    Et donc, en ObjC 2, cette directive est déconseillée (deprecated) en 32 bits et carrément absente en 64 bits... Pour la bonne et simple raison qu'avec le @synthesize on n'est plus obligé de définir d'ivar pour les propriétés ce qui ferait chier le @defs... Dans quel ordre mettre les ivars dans la structure ?

    Cependant, on peut toujours s'amuser à  construire la structure manuellement, l'avantage de @defs c'est qu'il donnait la structure exact quelque soit les changements...

    Et je ne suis toujours pas d'accord sur le fait qu'ObjC n'est fait que pour les interfaces, le système de messages n'est pas fait pour les traitements lourds, ça oui, mais tous les traitements moins lourds où ObjC n'est pas un problème s'étendent au-delà  de la simple interface... Sinon, quel intérêt d'avoir séparé Foundation et AppKit.
  • Philippe49Philippe49 Membre
    décembre 2008 modifié #61
    dans 1229072496:

    Et je ne suis toujours pas d'accord sur le fait qu'ObjC n'est fait que pour les interfaces, le système de messages n'est pas fait pour les traitements lourds, ça oui, mais tous les traitements moins lourds où ObjC n'est pas un problème s'étendent au-delà  de la simple interface... Sinon, quel intérêt d'avoir séparé Foundation et AppKit.

    Oui le mot "interface" que j'ai utilisé est réducteur. La ligne de partage est évidemment moins nette, et elle évolue dans le sens favorable à  Objective-C : c'est ce que tu m'avais fait comprendre dans un post précédent.

    dans 1229072496:

    Ce code n'est plus utilisable dans ObjC 2.

    J'ai réussi à  le faire fonctionner (?)

    <br />#import &lt;Foundation/Foundation.h&gt;<br /><br /><br />#define STACKCLASS(class) typedef struct { @defs(class) } &#092;<br />__CLASS_ON_STACK__##class;<br /><br /><br />#define STACKOBJECTISA(objectName,className,classIsa) &#092;<br />__CLASS_ON_STACK__##className __INSTANCE_ON_STACK__##objectName; &#092;<br />__INSTANCE_ON_STACK__##objectName.isa = classIsa; &#092;<br />className* objectName = (className*)&amp; __INSTANCE_ON_STACK__##objectName;<br /><br /><br />#define STACKOBJECT(objectName,className) &#092;<br />STACKOBJECTISA(objectName,className,[className class]);<br /><br />@interface Test :NSObject {<br />}<br />@end<br />@implementation Test<br />-(void) plop {<br />}<br />@end<br /><br /><br />STACKCLASS(Test);<br />int main(void) {<br />	int i;<br />	for (i=0; i&lt; 10000000; i++)<br />	{<br />		STACKOBJECT(test,Test);<br />		[test init];<br />		[test plop];<br />	}<br />	return 0;<br />}<br />
    
Connectez-vous ou Inscrivez-vous pour répondre.