A linguagem Objective-C é uma linguagem desenhada para criar sofisticados programas orientados a objetos. Objective-Cexpande o padrão ANSI C fornecendo sintaxe para a definição de classes e metódos, assim como outros tipos de estruturas que promovem a extensão dinâmica de classes.
Importante: Esse documento não se presta a ensinar nenhum aspecto da linguagem C. Se você não for familiarizado com C, deve ler sobre o básico antes de continuar.
Se você está familiarizado com a linguagem C e já programou com alguma linguagem orientada a objetos antes, as informações a seguir deverão lhe ajudar a entender a sintaxe básica do Objective-C. Muito dos conceitos de orientação a objetos tradicionais, como encapsulamento, herança e polimorfismo, todos estão presentes em Objective-C. Existem algumas diferenças importantes, mas elas foram deixadas de fora desse artigo e informações mais detalhadas estão disponiveis se necessário.
Objective-C: Um sub-conjunto de C
Objective-C é um sub-conjunto da versão ANSI da linguagem C e suporta a mesma sintaxe básica de C. Como no código C, você define arquivos de cabeçalho e arquivos de código fonte para separar as declarações públicas da implementação dos detalhes de seu código. Os arquivos de cabeçalho do Objective-C usam as extensões listadas na tabela abaixo:
Extensão | Tipo |
---|---|
.h |
Arquivos de cabeçalho. Esses arquivos contém a classes, tipo, funções e declarações de contantes. |
.m |
Arquivos de código fonte. Esta é a tipica extensão usada para arquivos e pode conter tanto código Objective-C quanto código C. |
.mm |
Arquivos de código fonte. Um arquivo com essa extensão pode conter código C++ em acdição ao código Objective-C e C. Essa extensão deveria ser usada se vocÊ se referir a classes ou recursos do C++ em seu código C++. |
Quando você quer incluir uma arquivo de cabeçalho em seu código, você tipicamente usa a diretiva #import. Ela funciona como o #include, exceto que se certifica que um mesmo arquivo nunca seja incluido mais de uma vez. Nos exemplos e documentação do Objective-C, o #import é sempre usado, e seus próprios códigos devem usa-lo também.
Classes
Como em muitas outras linguagens orientadas a objetos, as classes em Objective-C fornecem a estrutura básica para encapsular alguns dados com ações que atuam nesses dados. Um objeto é uma instância em tempo de execução de uma classe, e contém sua própria cópia das variáveis instânciadas pela classe e ponteiros para os metódos da classe.
A especificação de uma classe em Objective-C necessita de duas partes distintas: a interface e a implementação. A interface é a parte que contém a declaração e define as variáveis que serão instanciadas e os metódos associados com a classe. A interface é normalmente colocada num arquivo .h. A implementação é a parte que contém o código dos metódos da classe. A implementação é colocada em um arquivo .m.
A Figura 1-1 mostra a sintaxe para a declaração de uma classe chamada MyClass, que herda caracteristicas da classe base do Cocoa, NSObject. A declaração da classe começa com a diretiva de compilador @interface e termina com a diretiva @end. Logo após o nome da classe (e separado dele por dois pontos) fica o nome da classe-pai. As variáveis de instância da classe são declaradas em um bloco de código delineado por chaves ( { e } ). Após o bloco de variáveis fica a lista de metódos declaradas pela classe. Um ponto-e-virgula marca o fim de cada declaração de variavel ou metódo.
O exemplo abaixo mostra exemplos de tipificação forte e fraca:
MyClass *myObject1; // Strong typing |
id myObject2; // Weak typing |
Observe o asterisco na primeira declaração. No Objective-C, referências para objetos são ponteiros. Se isso não fizer sentido para você, não se preocupe – você não precisa ser um expert em ponteiros para ser capaz de programar em Objective_C. Você tem que se lembrar de colocar o asterisco na frente dos nomes de variáveis para declarações de objetos com tipificação forte. O tipo id implica um ponteiro.
Metódos e Mensagens
Uma classe no Objective-C pode declarar dois tipos de metódos: metódos de instância e metódos de classe. Um metódo de instância é um metódo cuja execução é associada a uma particular instância da classe. Em outras palavras, antes que você possa chamar um metódo de instância, precisa criar primeiro uma instância da classe. Metódos de classe, ao contrário, não requerem a criação de uma instância da classe.
A declaração de um metódo consiste de um identificados do tipo do metódo, um tipo de retorno, uma ou mais palavras-chaves, e o tipo do parametro e informação do nome. A Figure 1-2 mostra a declaração do metódo de instãncia insertObject:atIndex.
Essa declaração é precedida por um sinal de menos, que indica que este é um metódo de instância. O nome do metódo (insertObject:atIndex:) é uma concatenação de todas as palavras-chaves, incluindo os dois pontos, que declaram a presença de um parametro. Se um metódo não possui nenhum parametro, você omite os dois pontos depois da primeira (e apenas dela) palavra-chave. Nesse exemplo, o metódo pedi dois parametros.
Quando você quer chamar um metódo, você faz isso enviando uma mensagem para um objeto. Uma mesagem é a assinatura do metódo, junto com a informação dos parametros que o metódo necessita. Todas as mensagens que você envia para um objeto são disparadas dinâmicamente, o que facilita comportamentos polimorficos em classes Objective-C.
As mensagens são encapsuladas por colchetes ([ e ]). Dentro dos colchetes, o objeto que recebe a mensagem fica a esquerda e a mensagem (junto com qualquer parametro requerido pela mensagem) fica a direita. Por exemplo, para enviar a mensagem insertObject:atIndex: para um objeto da variavel myArray, você usa a seguinte sintaxe:
[myArray insertObject:anObject atIndex:0]; |
Para evitar declarar muitas variáveis locais para armazenar resultados temporários, o Objective-C deixa você aninhar mensagens. O valor do retorno de cada mensagem aninhada é usada como parametro, ou como alvo, de outra mensagem. Por exemplo,você poderia substituir qualquer uma das variáveis usadas no exemplo anterior por mensagens que retornem os valores. Assim, se você tiver outro objeto chamado myAppObject que tem dois metódos para acessar um array o objeto para inserir dados no array, você pode re-escrever o exemplo anterior da seguinte forma:
[[myAppObject theArray] insertObject:[myAppObject objectToInsert] atIndex:0]; |
O Objective-C também fornece uma sintaxe de ponto para invocar metódos de acesso. Esse tipo de metódo obtém e alteram o estado de um objeto, e tipicamente são da forma -(type) propertyName – (void) setPropertyName: (type). Usando essa sintaxe, você poderia escrever o exemplo anterior assim:
[myAppObject.theArray insertObject:[myAppObject objectToInsert] atIndex:0]; |
Você pode usar também essa sintaxe dessa forma:
myAppObject.theArray = aNewArray; |
Essa é simplesmente uma sintaxe diferente para escrever: [myAppObject setTheArray:aNewArray];
.
Apesar dos exemplos acima enviarem mensagens para uma instância de uma classe, você pode também pode enviar mensagens para a própria classe, Quando uma classe recebe uma mensagem, o metódo que você especificou precisa tar sido definido como metódo de classe ao invés de metódo de instância.
Tipicamente, metódos de classe são usados como metódos para criação de novas instâncias de classe ou acessar pedações de informação compartilhada associados com a classe. A sintaxe de um metódo de classe é identico a um metódo de instância, com uma exceção. Ao invéis de usar um sinal de menos para o identificador do tipo do metódo, usa-se um sinal de mais.
O exemplo abaixo ilustra como usar uma metódo de classe como um metódo de criação de uma classe. Nesse caso, o metódo array é um metódo de classe de NSArray – e herda de NSMutableArray – que aloca e inicializa uma nova instância da classe e retorna ela para seu código.
NSMutableArray *myArray = nil; // nil is essentially the same as NULL |
// Create a new array and assign it to the myArray variable. |
myArray = [NSMutableArray array]; |
A Listagem 1-1 mostra a implementação da MyClass do exemplo anterior. Como a decalração da classe, a sua implementação é identificada por duas diretivas – aqui, @implementation e @end. Essas diretivas fornecem a informação de escopo que o compilador precisa para associas os metódos encapsulados com a classe correspondente.
Listing 1-1 A class implementation
@implementation MyClass |
- (id)initWithString:(NSString *)aName |
{ |
self = [super init]; |
if (self) { |
name = [aName copy]; |
} |
return self; |
} |
+ (MyClass *)createMyClassWithString: (NSString *)aName |
{ |
return [[[self alloc] initWithString:aName] autorelease]; |
} |
@end |
Declarando Propriedades
Propriedades são uma notação conveniente usada para substituir a declaração e, opcionalmente, a implementação de metódos de acesso.
Você inclui declarações de propriedades com as declarações de metódos da interface de sua classe. A definição básica usa a diretiva @property, seguida pela informação do tipo e nome da propriedade. Você também pode configurar a propriedade com opções personalizadas, que definem como o metódo de acesso age. O exemplo abaixo mostra algumas declarações simples de propriedades:
@property BOOL flag; |
@property (copy) NSString *nameObject; // Copy the object during assignment. |
@property (readonly) UIView *rootView; // Declare only a getter method. |
Cada propriedade para leitura fornece um metódo com o mesmo nome da propriedade. Cada propriedade para escrita fornece uma metódo adicional da forma setPropertyName:, onde a primeira letra do nome da propriedade é maiuscula.
Na sua implementação da classe, você pode usar a diretiva @synthesize para solicitar que o compilador gere os metódos de acordo com a especificação da declaração.
@synthesize flag; |
@synthesize nameObject; |
@synthesize rootView; |
Você pode combinar as sentenças @synthesize numa única linha se você quiser:
@synthesize flag, nameObject, rootView; |
Na prática, as propriedades reduzem a quantidade de código redudante que você tem que escrever. Por muitos metódos de acesso serem implementados de modo similar, as propriedades eliminam a necessidade de implementar metódos getter e setter para cada propriedade exposta na classe. Ao invés disso, você especifica o comportamente que quer usando a declaração da propriedade e então sintetiza metódos getter e setter baseados na declaração em tempo de compilação.
Strings
Como um sub-conjunto de C, o Objective-C suporta as mesmas convenções para especificação de string que o C. Em outras palavras, caracteres indicviduais são encapsulados por aspa única, e cadeias de caracteres são cercadas por aspas duplas. Todavia, o framework do Objective-C tipicamente não usa string no estilo C. Ao invés disso, ele passa strings através de objetos NSString.
A classe NSString fornece um invólucro para strings que possui todas a vantagens que você experaria, incluido gerenciamente de memória para armazenar strings de tamanho arbitrário, suporte a Unicode, utilitários de formatação estilo printf, e mais. Já que string são muito usadas, o Objective-C fornece uma notação curta para criar objetos NSString a partir de valores constantes. Para usar esse atalho, tudo que você tem que fazer é preceder uma string normal com aspas dulas com o simbolo @, como mostrado abaixo:
NSString *myString = @"My String\n"; |
NSString *anotherString = [NSString stringWithFormat:@"%d %@", 1, @"String"]; |
// Create an Objective-C string from a C string |
NSString *fromCString = [NSString stringWithCString:"A C string" encoding:NSASCIIStringEncoding]; |
Protocolos
Um protocolo declara metódos que podem ser implementados por qualquer classe. Protocolos não são classes. Eles simplesmente definem uma interface que outros objetos serão responsaveis por implementar. Quando você implementa os metódos de um protocolo em uma de suas classes, sua classe é dita que está em conformidade com esse protocolo.
Protocolos são usados frequentemente para especificar a interface de objetos de delegação. A melhor maneira para observar o funcionamente de protocolos, objetos de delegação e outros objetos é através de um exemplo.
A classe UIApplication implementa o comportamente necessário de uma aplicação. Ao invés de forçar você a criar uma sub-classe de UIApplication para receber notificações simples sobre o estado atual da aplicação, a classe UIApplication entrega essas notificações através de chamadas específicas a metódos do objeto de delegação correspondente. Um objeto que implementa os metódos do protocolo UIApplicationDelegate pode receber essas notificações e fornecer a resposta apropriada. Você especifica que sua classe está em conformidade ao, ou adota um, protocolo colocando no bloco da interface o nome do protocolo entre “<>” depois do nome da classe da qual ela herda suas caracteristicas. Você não tem que declarar os metódos do protocolo que você implementa.
@interface MyClass : NSObject <UIApplicationDelegate, AnotherProtocol> { |
} |
@end |
A declaração de um protocolo parece similar a uma interface de classe, com execeção que o protocolo não possui classes-pai e eles não definem variáveis de instância. O exemplo abaixo mostra uma declaração simples de um protocolo com um metódo:
@protocol MyProtocol |
- (void)myProtocolMethod; |
@end |
Para mais informação
A informação acima foi escrita para que você se familiarize com o básico sobre a linguagem Objective-C. O assunto coberto aqui reflete as caracteristicas de languagem que você mais encontra ao ler o restante da documentação. Esses não são todos os recursos da linguagem, e vocÊ encontra mais sobre a linguagem emThe Objective-C Programming Language.
Fonte: http://developer.apple.com/library/ios/#referencelibrary/GettingStarted/Learning_Objective-C_A_Primer/index.html#//apple_ref/doc/uid/TP40007594