Objective-C: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
Messbot (discussione | contributi)
m Protocolli: fix errore Lint - Tag di chiusura mancante using AWB
ValterVBot (discussione | contributi)
m tag source deprecati, replaced: <source lang= → <syntaxhighlight lang= (33), </source> → </syntaxhighlight> (33)
Riga 56:
==== Proprietà ====
Mentre precedentemente le variabili d'istanza richiedevano metodi espliciti di lettura e scrittura (detti ''getters'' e ''setters''), Objective C 2.0 introduce le proprietà (''property'') con la seguente sintassi:
<sourcesyntaxhighlight lang="objc">
@interface Persona: NSObject {
}
Riga 63:
-(id)initWithName:(NSString)nome eta:(int)eta;
@end
</syntaxhighlight>
</source>
Una volta inserite nell'interfaccia, si può accedere alle proprietà usando la notazione descritta nell'esempio:
<sourcesyntaxhighlight lang="objc">NSString *nome = unaPersona.nome;</sourcesyntaxhighlight>
Il compilatore traduce questa notazione in chiamate di metodi accessori. L'istruzione precedente è equivalente a:
<sourcesyntaxhighlight lang="objc">NSString *nome = [unaPersona nome];</sourcesyntaxhighlight>
 
==== Enumerazione veloce ====
Invece di usare un oggetto enumeratore per operare iterazioni all'interno di una raccolta di oggetti, Objective C 2.0 offre una sintassi di ciclo dedicata; riprendendo l'esempio precedente:
<sourcesyntaxhighlight lang="objc">
for (Persona *persona in laGente)
NSLog(@"%@ ha %i anni.", persona.nome, persona.eta);
</syntaxhighlight>
</source>
 
==== Portable Object Compiler ====
Riga 86:
 
Si dice che un oggetto chiamato ''ogg'' la cui [[classe (informatica)|classe]] implementa il metodo ''faiQualcosa'', ''risponde'' al messaggio ''faiQualcosa''. L'invio del messaggio ''faiQualcosa'' all'oggetto ''ogg'' è espresso da:
<sourcesyntaxhighlight lang="objc">[ogg faiQualcosa];</sourcesyntaxhighlight>
 
mentre l'azione equivalente in C++ e Java sarebbe espressa da:
<sourcesyntaxhighlight lang="cpp">ogg.faiQualcosa();</sourcesyntaxhighlight>
 
In questo modo è possibile inviare messaggi ad un oggetto anche se l'oggetto ''non è capace'' di rispondere. Questo differisce dai linguaggi [[tipo di dato|tipizzati]] staticamente come C++ e [[Java (linguaggio di programmazione)|Java]] nei quali tutte le chiamate devono essere di metodi predefiniti.
Riga 99:
L'interfaccia di una classe è solitamente definita in un file ".h". La convenzione usata è quella di assegnare il nome al file basandosi sul nome della classe, nell'esempio "NomeDellaClasse.h".
 
<sourcesyntaxhighlight lang="objc">
//definizione dell'interfaccia: "NomeDellaClasse.h"
 
Riga 122:
 
@end
</syntaxhighlight>
</source>
 
Il segno meno (-) denota i metodi d'istanza, mentre il segno più (+) quello di classe (analoghi alle funzioni statiche del C++). Si noti la differenza di significato con le convenzioni dei [[Unified Modeling Language|diagrammi UML]] dove i due segni rappresentano rispettivamente i metodi privati e pubblici.
Riga 130:
La convenzione usata è quella di assegnare il nome al file basandosi sul nome della classe, nell'esempio "NomeDellaClasse.m"
 
<sourcesyntaxhighlight lang="objc">
//definizione dell'implementazione: "NomeDellaClasse.m"
 
Riga 160:
 
@end
</syntaxhighlight>
</source>
 
I metodi sono scritti in maniera diversa dalle [[funzione (informatica)|funzioni]] in stile C. Ad esempio, una funzione, sia in C che in Objective C segue la seguente forma generale:
 
<sourcesyntaxhighlight lang="objc">
int fai_la_radice_quadrata(int i)
{
return radice_quadrata(i);
}
</syntaxhighlight>
</source>
 
che avrà come prototipo:
 
<sourcesyntaxhighlight lang="objc">int fai_la_radice_quadrata(int);</sourcesyntaxhighlight>
 
L'implementazione come metodo diverrà:
 
<sourcesyntaxhighlight lang="objc">
- (int) fai_la_radice_quadrata:(int) i
{
return [self radice_quadrata: i];
}
</syntaxhighlight>
</source>
 
Un approccio più canonico alla scrittura del metodo sarebbe quello di citare il primo argomento nel nome del selettore:
 
<sourcesyntaxhighlight lang="objc">
- (int) faiLaRadiceQuadrataDiInt: (int) i
{
return [self radiceQuadrataDiInt:i];
}
</syntaxhighlight>
</source>
 
Questa sintassi può apparire complicata, ma consente di assegnare i nomi ai [[parametro (informatica)|parametri]], ad esempio:
 
<sourcesyntaxhighlight lang="objc">
- (int) changeColorWithRed:(int) r green:(int) g blue:(int) b
</syntaxhighlight>
</source>
 
può essere invocato così:
<sourcesyntaxhighlight lang="objc">
[myColor changeColorWithRed:5 green:2 blue:6];
</syntaxhighlight>
</source>
 
Le rappresentazioni interne di questi metodi possono variare con le diverse implementazioni di Objective C.
Riga 219:
 
La sintassi
<sourcesyntaxhighlight lang="objc">
@protocol Locking
- (void)lock;
- (void)unlock;
@end
</syntaxhighlight>
</source>
indica che esiste un'idea astratta di [[lock]]ing che può essere usata; quando è dichiarata in una definizione di classe
<sourcesyntaxhighlight lang="objc">
@interface NomeClasse : NomeSuperClasse <Locking>
@end
</syntaxhighlight>
</source>
indica che le istanze di ''NomeClasse'' forniranno un'implementazione per i due metodi d'istanza come meglio crederanno. Questa specifica astratta è particolarmente utile per descrivere il comportamento desiderato ad esempio di [[plugin (informatica)|plugin]] senza porre nessuna limitazione su quella che dovrà essere la gerarchia d'implementazione.
 
Riga 236:
 
Informazioni di tipizzazione statica possono essere aggiunte eventualmente alle variabili. Tali informazioni sono controllate nel [[compile-time]]. Nelle istruzioni seguenti, vengono fornite informazioni di tipo sempre più specifiche. Le istruzioni sono equivalenti durante l'esecuzione, ma le informazioni consentono al compilatore di avvisare il programmatore se gli argomenti passati non corrispondono ai tipi specificati. Nella prima istruzione, l'oggetto deve conformarsi al protocollo ''aProtocol'' e, nella seconda, deve essere un membro della classe ''NSNumber''.
<sourcesyntaxhighlight lang="objc">
- setMyValue:(id <aProtocol>) foo;
- setMyValue:(NSNumber*)foo;
</syntaxhighlight>
</source>
La tipizzazione dinamica può essere una caratteristica molto potente. Se si implementano [[classe container|classi container]] usando linguaggi a tipizzazione statica come Java (prima della versione 1.5), il programmatore è costretto a scrivere classi container per oggetti generici e poi usare la [[conversione di tipo]] per adattarli ad oggetti specifici; tale conversione, comunque, contraddice la disciplina semantica della tipizzazione statica.
 
Riga 247:
Il [[run-time system]] di Objective C specifica una coppia di metodi della classe <code>Object</code>
* metodi di forwarding:
<sourcesyntaxhighlight lang="objc">
- (retval_t) forward:(SEL) sel :(arglist_t) args; // con GCC
- (id) forward:(SEL) sel :(marg_list) args; // con sistemi NeXT/Apple
</syntaxhighlight>
</source>
* metodi di azione:
<sourcesyntaxhighlight lang="objc">
- (retval_t) performv:(SEL) sel :(arglist_t) args; // con GCC
- (id) performv:(SEL) sel :(marg_list) args; // con sistemi NeXT/Apple
</syntaxhighlight>
</source>
e se un oggetto vuole implementare il forwarding necessita solamente di "[[override|sovrascrivere]]" i metodi di forwarding per definire il proprio comportamento. I metodi di azione <code>performv::</code> non necessitano override.
 
Riga 262:
 
; ''Forwarder.h''
<sourcesyntaxhighlight lang="objc">
#import <objc/Object.h>
Riga 275:
@end
</syntaxhighlight>
</source>
 
; ''Forwarder.m''
<sourcesyntaxhighlight lang="objc">
#import "Forwarder.h"
Riga 307:
}
@end
</syntaxhighlight>
</source>
 
; ''Recipient.h''
<sourcesyntaxhighlight lang="objc">
#import <objc/Object.h>
Riga 317:
- (id) hello;
@end
</syntaxhighlight>
</source>
 
; ''Recipient.m''
<sourcesyntaxhighlight lang="objc">
#import "Recipient.h"
Riga 333:
@end
</syntaxhighlight>
</source>
 
; main.m
<sourcesyntaxhighlight lang="objc">
#import "Forwarder.h"
#import "Recipient.h"
Riga 357:
return 0;
}
</syntaxhighlight>
</source>
 
==== Note ====
Riga 391:
 
; ''Integer.h''
<sourcesyntaxhighlight lang="objc">
#include <objc/Object.h>
Riga 402:
- (id) integer: (int) _integer;
@end
</syntaxhighlight>
</source>
 
; ''Integer.m''
<sourcesyntaxhighlight lang="objc">
#import "Integer.h"
 
Riga 420:
}
@end
</syntaxhighlight>
</source>
 
; ''Arithmetic.h''
<sourcesyntaxhighlight lang="objc">
#import "Integer.h"
 
Riga 430:
- (id) sub: (Integer *) subtrahend;
@end
</syntaxhighlight>
</source>
 
; ''Arithmetic.m''
<sourcesyntaxhighlight lang="objc">
#import "Arithmetic.h"
 
Riga 447:
}
@end
</syntaxhighlight>
</source>
 
; ''Display.h''
<sourcesyntaxhighlight lang="objc">
#import "Integer.h"
 
Riga 457:
- (id) showint;
@end
</syntaxhighlight>
</source>
 
; ''Display.m''
<sourcesyntaxhighlight lang="objc">
#import "Display.h"
 
Riga 481:
}
@end
</syntaxhighlight>
</source>
 
; ''main.m''
<sourcesyntaxhighlight lang="objc">
#import "Integer.h"
#import "Arithmetic.h"
Riga 505:
[num1 showint];
}
</syntaxhighlight>
</source>
 
==== Note ====
Riga 525:
 
Ad esempio:
<sourcesyntaxhighlight lang="objc">
@interface CustomNSApplication : NSApplication
@end
Riga 537:
class_poseAs ([CustomNSApplication class], [NSApplication class]);
</syntaxhighlight>
</source>
 
Questo intercetta ogni invocazione a setMainMenu di NSApplication.
Riga 549:
 
Alcuni compilatori, compreso [[GNU Compiler Collection|GCC]], supportano la clausola ''#import'' anche per il linguaggio C; il suo uso viene comunque scoraggiato sulla base del fatto che l'utilizzatore dei file da includere dovrebbe distinguere quali file includere solo una volta da quelli progettati per essere inclusi più volte. Questo onere dovrebbe in teoria essere a carico dell'implementatore del file da includere che può usare la direttiva ''#pragma once'' o usare la [[Include guard|tradizionale tecnica]]:
<sourcesyntaxhighlight lang="Cpp">
#ifndef H_PERSONA
#define H_PERSONA
// ... contenuto di header.h ...
#endif
</syntaxhighlight>
</source>
In questo caso le direttive ''#include'' e ''#import'' diventano equivalenti.