quinta-feira, 16 de dezembro de 2010

OBJECTIVE-C


Objc

Olá pessoal. Percebendo a necessidade de algumas pessoas em entender alguns conceitos do Objective-C, estou disponibilizando este tutorial feito por Alberto Martins que encontrei na net. Divirtam-se…


Antes de começar este tutorial gostaria de responder a uma pegunta do Arthur Lopes:
O asterisco no Objective-C tem uma função especial. Ele define a variável como um ponteiro. Os ponteiros são concebidos para armazenar endereços de memória. Com um ponteiro você pode indiretamente manipular os dados armazenados em outras variáveis. Ou seja você cria aquela variável com a referência para outro objeto. Enquanto sem asterisco você cria variáveis por valor.


Ex:
NSArray foo;
Você não deve dizer que foo é um NSArray. Ainda. Ele está apenas pronto para apontar para um (e nesse momento está apontando para NULL “nulo”), até você fazer isto:
foo = new NSArray(…)
Agora foo está apontando para um objeto NSArray.
Você pode ter ponteiros para tipos básicos:
int i = 5; // i é um tipo integer básico
int* x; // x é um PONTEIRO para um integer
x = &i; // x agora aponta para o mesmo espaço de memória que “i” está.
Agora nós podemos referenciar o ponteiro “x” e usar ele para mudar o valor de “i”.
*x = 7; // atribui o valor da variável onde o ponteiro está apontando, para 7
Espero que ajude. Qualquer dúvida procure por “Tipo valor, Tipo referência” no google que vai ter bastante material.
Vamos ao tuto..


Objective-C

Introdução

    Este breve tutorial foi criado para suprir a falta de informação sobre a linguagem Objective-C no Brasil, e com isso incentivar sua popularização. Para aqueles que já programam em C, a adaptação ao paradigma de orientação à objetos por meio da linguagem Objective-C ocorre de forma simples e natural, visto que sintaticamente apenas poucas construções são adicionadas. Observamos que no momento este não é um tutorial completo, ou seja, conhecer um pouco de C será não apenas de grande valia, como praticamente necessário para construir programas mais complexos. Devemos salientar também que por enquanto não iremos utilizar o framework “Foundation”, nem qualquer outro, nos mantendo nos rudimentos da linguagem.A linguagem Objective-C foi criada por Brad Cox e sua empresa, a StepStone Corporation, no início da década de 80. Em 88 ela foi licenciada pela NeXT, tornando-se a linguagem de desenvolvimento do NeXTstep. O suporte do GNU/gcc foi acrescentado em 1992. Em 1994 as empresas NeXT Computer e Sun Microsystems criaram uma especificação do NeXTstep conhecida como OpenStep. A implementação da Free Software Foundation da especificação OpenStep é denominada GNUStep. Atualmente Objective-C é utilizada como a principal linguagem de programação do MacOS X, que é baseado no NeXTstep. A versão da Apple do ambiente NeXTStep/GNUStep com adições é denominada Cocoa.

Características

    Objective-C é apenas um conjunto de adições à linguagem C. Ela dá ao C suporte à construções orientadas a objetos como as da Smalltalk. Objective-C suporta polimorfismo, posing, categorias, e é uma linguagem dinâmica, com typing e binding dinâmicos. Com Objective-C você pode adicionar classes e categorias em tempo de execução de forma fácil. E tudo isso com uma sintaxe de mensagem simples e elegante: olhe os títulos destas subseções e você já saberá como conversar com os objetos! Objective-C realiza chamadas de mensagem dinâmicas rapidamente, entre 1,5 e 2,0 vezes o tempo de uma chamada de função em C.

Programação Orientada à Objetos

    O conceito de orientação à objetos é na verdade algo muito simples. Diariamente utilizamos objetos para realizar tarefas, e programar OO não é nada alem disso.Programadores mais antigos estão acostumados a pensar a programação separando dados e fuções que seriam aplicadas neles. A própria forma de pensar era diferente; para alguns problemas era óbvia a necessidade de uma integração maior entre os dados e as funções, e isto foi o aparecimento do objeto. Tomando um exemplo simples: supomos que você possua uma televisão. A não ser que você seja um milhonário ou um professor pardal, essa televisão deve ter saído de uma linha de montagem, sendo assim igual a muitos outros aparelhos do mesmo modelo. Entretanto essa é a sua televisão, e ela possui um número de identificação (ou número serial) único. No exemplo acima e agora traduzindo para o conceito de OO, sua televisão é uma instância da classe televisão. E cada vez que uma nova televisão é produzido, uma nova instância da classe televisão é criada. Existem também certas coisas que você pode fazer com a sua televisão, como ligar e desligar, modificar o volume e configurações de cor, ligar o PIP, etc. As funções realizadas com a televisão, em OO, denominam-se métodos. Em alguns casos os métodos são aplicados na instância da classe, em outros eles são aplicados na classe em si. Por exemplo, ligar a televisão seria um método de instância e descobrir quantos televisores foram produzidos por um determinado fabricante seria um método de classe. Quando vamos comprar um televisor em alguma loja, costumamos encontrá-los agrupados junto com tocadores de DVD, por exemplo. Bem, isso não se dá por acaso: televisores, assim como tocadores de DVD são eletrônicos, e com isso possuem características e funções em comum. Podemos então pensar nestes dois aparelhos como sendo instâncias de uma classe denominada eletrônicos. Entretanto não queremos instâncias da classe eletrônicos, e sim das classes televisão e toca-DVD, logo dizemos que as classes televisão e toca-DVD são subclasses (ou classes filhas) da superclasse (ou classe pai) eletrônicos. Esse é um conceito muito importante em orientação à objetos, e é denominado herança: quando criamos uma subclasse ela herda as características e métodos de sua superclasse. Nesse caso podemos dizer que nunca iremos criar uma instância da classe eletrônicos, logo esta é denominada uma classe abstrata, ou seja, uma classe que serve apenas para ser superclasse de outras classes.

Ambiente de programação

    Para programar em Objective-C, tal como em qualquer outra linguagem moderna, você precisa de um editor e um compilador. Ambos estão disponíveis gratuitamente em muitos dos sistemas operacionais atuais.No MacOS X, você deve instalar os “Developer Tools” gratuitos da Apple, caso eles não estejam presentes no seu sistema. Essas ferramentas incluem dentre muitas outras coisas o compilador gcc e um ambiente de programação extremamente eficiente, denominado Xcode. No Linux você já deve ter o gcc instalado, bem como muitos editores de texto (vi, pico, emacs). Você tambem pode utilizar algum ambiente de programação, como o KDevelop ou ferramentas GNUStep. No Windows você pode instalar o compilador Objective-C que acompanha o sistema MinGW (http://www.mingw.org). Para escrever os códigos, qualquer editor de texto puro, como o Notepad, ou algum ambiente de programação devem servir. Nos três sistemas, compilar um programa utilizando a linha de comando resume-se ao gcc (para projetos maiores costuma-se utilizar ferramentas como make, automake, etc), cujo formato geral de chamada é:
    gcc arquivos.m -o nome_do_programa -l objc
    Os arquivos de código da linguagem Objective-C possuem sufixo “.m”, enquanto que os cabeçários possuem, como em C, sufixo “.h”. Por algum motivo alguem na FSF não parece gostar muito de uma diretriz de pré-processamento (mais sobre isso depois) do Objetive-C denominada “#import”, que serve para substituir “#include” de forma a não ser necessário escrever “#ifndef #define #endif” para não incluir o mesmo arquivo várias vezes, e com isso as versões do gcc utilizadas em computadores com Linux e Windows dão “Warnings” na hora de compilar. Para acabar com esse problema, utilize a chamada do gcc com “-Wno-import”. Computadores com o gcc fornecido pela Apple não sofrem desse problema. Para compilar programas utilizando o Xcode da Apple você deve criar um novo projeto do tipo “Cocoa Application” e sobrescrever o arquivo “main.m” que será criado automaticamente.

Meu primeiro programa: classes, objetos e métodos

    Nesta seção vamos implementar um programa básico, já utilizando conceitos de programação orientada à objetos.Os programas em Objective-C possuem quatro partes bem definidas . A primeira define diretrizes para o pré-processador, a segunda define as classes e métodos, a terceira a implementa os métodos e a quarta é o programa em si. Mais tarde mostraremos como cada parte pode ficar armazenada em um arquivo separado, facilitando a organização do programa em si. Para facilitar, podemos iniciar lendo o programa a seguir que define nossa primeira classe, o Gato. Esse dócil animal mia, logo vamos implementar uma classe “Gato” que possui um método chamado “miau” que serve apenas para escrever “Miaau!” na tela. Veja o código: meuGato.m
    //
    // Programa Gato
    // 
    // por Alberto GOK Martins
    // para o tutorial de ObjC
    //
    
    // aqui comecam as diretrizes do pre-processador
    #import 
    #import 
    
    // aqui comeca a definicao das interfaces
    @interface Gato: Object
    
    -(void) miau;
    
    @end
    
    // aqui comecam as implementacoes dos metodos
    @implementation Gato
    
    -(void) miau
    {
            printf("Miaau!\n");
    }
    
    @end
    
    // aqui comeca o programa
    int main( int argc, const char *argv[] )
    {
            Gato *meuGato;
    
            meuGato = [Gato alloc];
            meuGato = [meuGato init];
    
            [meuGato miau];
    
            [meuGato free];
    
            return 0;
    }
    Todas as linhas que iniciam por “//” são linhas de comentários. Estas são ignoradas, logo é permitido escrever qualquer coisa após as duas barras. Comentários são utilizados para documentar um programa, facilitando sua compreensão. Outra forma de inserir comentários em programas Objective-C é utilizar os caracteres “/*” no início do comentário e “*/” no final; desta forma pode-se criar blocos de comentário com muitas linhas, sem que seja necessário escrever “//” a cada linha nova. As linhas iniciadas por “#” são diretrizes de pré-processamento. No programa acima utilizamos “#import <…>”, que diz para o compilador localizar, processar e importar informações dos arquivos “stdio.h” e “objc/Object.h”, ambos arquivos do sistema. Estes arquivos contém informações sobre a rotina “printf” e a classe “Object”, que foram utilizadas no nosso programa. A segunda parte do arquivo consiste na definição das Classes e de suas interfaces. Quando nós definimos uma nova classe é necessário dizer ao compilador algumas coisas. A primeira delas é falar de onde a classe vem, ou seja quem é a sua superclasse. Utilizamos para isso a seção “@interface”, cujo formato geral é:
    @interface NovaClasse: SuperClasse
    {
            Declaração_de_variáveis;
    }
    
    Declaração_de_métodos;
    
    @end
    No nosso programa definimos a classe “Gato”, que por enquanto não possui variáveis e apenas um método, o “miau”. Esse é um método da instância da classe “Gato” pois sua declaração é iniciada com o símbolo “-”. Poderíamos também criar um método da própria classe “Gato” utilizando o símbolo “+” para, por exemplo, contar o número de gatos que foram criados no programa. Após o sinal “-” temos a declaração entre parênteses do que o método irá retornar; no caso, “void”, indica que nada será retornado. Finalmente temos o nome do método. Mais adiante forneceremos o formato geral de declaração de métodos. A terceira parte do arquivo é a implementação dos métodos da classe. Ela define os métodos, ou seja contém seus códigos, declarados na parte “@interface”. O formato é:
    @interface NovaClasse 
    
    Definição_de_métodos;
    
    @end
    A definição de um método nada mais é do que sua declaração sem o caractere “;” acompanhada por seu código, que é colocado entre chaves “{” e “}”. No nosso programa, o método “miau” tem o código definido por uma instrução da biblioteca “stdio.h” chamada “printf”, que serve para mostrar caracteres na tela. A quarta e última parte do arquivo, é o programa em si. Esta parte contem a rotina denominada “main” que indica precisamente onde o programa deve iniciar sua execução. Ela inicia com a palavra “int”, especificando que “main” deve retornar um valor inteiro ao sistema quando terminar sua execução. As palavras que aparecem entre parêntesis “()” servem para lidar com argumentos passados pela linha de comando. A primeira linha da rotina “main” define uma variável chamada “meuGato”, dizendo que “meuGato” é um objeto que guardará valores da classe “Gato”. O asterísco diz que “meuGato” é um ponteiro para um “Gato”. Na segunda linha alocamos espaço na memória para o “meuGato”, e na terceira inicializamos as variáveis que podem estar presentes dentro do “meuGato”. Observe que na segunda linha passamos uma mensagem para a classe “Gato”, enquanto que na terceira a mensagem vai para a instância “meuGato”. Os métodos “alloc” e “init” não foram escritos por você, entretanto podemos utilizá-los pois foram definidos para a classe “Object”, que é a superclasse de “Gato”. Na quarta linha passamos uma mensagem para o objeto “meuGato”, dizendo para ele miar, ou seja, executar o método “miau” que implementamos. Na quinta linha passamos uma mensagem para “meuGato” dizendo que ele não será mais necessário, e que podemos liberar a memória que foi reservada à ele. Na sexta linha especificamos o valor que o programa deve retornar ao sistema; no caso 0, indicando que tudo ocorreu bem. Vamos finalmente compilar e executar o nosso programa. Para gerar o executável deve-se utilizar um compilador, no caso o gcc, e como visto anteriormente sua chamada (desta vez já com os nomes dos arquivos corretos) é:
    gcc meuGato.m -o meuGato -l objc
    Executando o arquivo “meuGato” deve-se obter a seguinte saída:
    Miaau!
    Um gato mais real… Vejamos agora um programa um gato um pouco mais elaborado. Todos devemos concordar que os gatos possuem certas características, como cor do pêlo, tamanho, peso, etc. Logo está faltando algo ao nosso gato. No programa a seguir implementamos o peso, bem como funções para defini-lo e obtê-lo; fica para você a tarefa de implementar as outras características.
    //
    // Programa Gato com caracteristica
    // 
    // por Alberto GOK Martins
    // para o tutorial de ObjC
    //
    
    // aqui comecam as diretrizes do pre-processador
    #import 
    #import 
    
    // aqui comeca a definicao das interfaces
    @interface Gato: Object
    {
            double peso;
    }
    
    -(void) miau;
    -(void) setPeso: (double) p;
    -(double) getPeso;
    
    @end
    
    // aqui comecam as implementacoes dos metodos
    @implementation Gato
    
    -(void) miau
    {
            printf("Miaau!\n");
    }
    
    -(void) setPeso: (double) p
    {
            peso=p;
    }
    
    -(double) getPeso
    {
            return peso;
    }
    
    @end
    
    // aqui comeca o programa
    int main( int argc, const char *argv[] )
    {
            Gato *meuGato;
            Gato *meuGato2;
    
            meuGato = [[Gato alloc] init];
            meuGato2 = [[Gato alloc] init];
    
            [meuGato setPeso: 4.2];
            [meuGato2 setPeso: 4.9];
            [meuGato miau];
            [meuGato2 miau];
            printf("meuGato pesa: %lf kg\n",[meuGato getPeso]);
            printf("meuGato2 pesa: %lf kg\n",[meuGato2 getPeso]);
    
            [meuGato free];
            [meuGato2 free];
    
            return 0;
    }
    A primeira adição no programa acima em relação ao original são as declarações dos métodos “setPeso” e “getPeso”. O primeiro recebe um valor real do tipo double, e o segundo retorna um valor tipo double. Estamos prontos para enunciar um formato geral de declaração de métodos:
    tipo_de_método(tipo_do_retorno_do_método) nome_do_método: (tipo_do_argumento) argumento;
    
    exemplo de método de classe:
    
            +(int) quantosGatos;
    
    exemplo de método de instância:
    
            -(void) setPeso: (double) p;
    Na parte de implementação temos as implementações de “setPeso” e “getPeso”. Na rotina “main” podemos notar que estamos criando dois gatos diferentes. O primeiro pesa 4.2kg, enquanto que o segundo 4.9kg. Devemos observar que, de modo distinto do programa original, estamos alocando memória e inicializando “meuGato” ao mesmo tempo. Essa é uma construção muito utilizada, junto com a alternativa seguinte:
    Gato *meuGato = [[Gato alloc] init];
    Podemos observar, ainda dentro da rotina “main”, como passar argumentos para o objeto “meuGato”, com o método setPeso. Ou também como obter o valor de uma característica do “meuGato”, com o método “getPeso” e imprimi-lo na tela com a função “printf”. A saída agora deve ser:
    Miaau!
    Miaau!
    meuGato pesa: 4.200000 kg
    meuGato2 pesa: 4.900000 kg

Mais sobre classes, objetos, métodos

    Na seção anterior vimos como passar um argumento para um método. Entretanto muitas vezes é desejável poder passar mais do que um argumento por vez, por exemplo para definir a posição (x,y) de um ponto no R2. Felizmente existe um tipo de construção que nos permite fazê-lo:
    -(tipo) nome: (tipo) variável nome: (tipo) variável;
    
    exemplo, um método para definir as posições de um ponto no R2:
    
    -(void) setX: (double) x andY: (double) y;
    
    passando a mensagem:
    
    [Objeto setX: 1.511 andY: 2.332];
    Geralmente é interessante ter métodos para definir cada argumento separadamente, ainda que existam os métodos para definir múltiplos argumentos de uma só vez. Um método também pode retornar um objeto. Por exemplo, poderíamos implementar um método de instância na classe “Gato” que definisse uma reprodução sexuada. Para isso temos que ter duas instâncias da classe “Gato” allocadas e inicializadas; uma para receber a mensagem e outra para ser o objeto a ser recebido como argumento da mensagem. Devemos ter também um objeto do tipo “Gato”, que armazenará o gato filho. Acompanhe a definição do método “reproduzir”:
    
    -(Gato *) reproduzir: (Gato *) Gato2
    {
            // funcao para criar um gato filho com a media dos pesos dos pais
            // antes de algum protesto, nao estamos tentando ser biologicamente corretos!
    
            Gato *Gatinho=[[Gato alloc] init];
            double pesoGatinho;
    
            pesoGatinho = (peso+[Gato2 getPeso])/2;
    
            [Gatinho setPeso: pesoGatinho];
    
            return Gatinho;
    }
    
    
    int main( int argc, const char *argv[] )
    {
            Gato *meuGato = [[Gato alloc] init];
            Gato *meuGato2 = [[Gato alloc] init];
            Gato *meuGatoFilho;
    
            [meuGato setPeso: 4.2];
            [meuGato2 setPeso: 4.9];
            [meuGato miau];
            [meuGato2 miau];
    
            meuGatoFilho = [meuGato reproduzir: meuGato2];
            [meuGatoFilho miau];
    
            printf("meuGato pesa: %lf kg\n",[meuGato getPeso]);
            printf("meuGato2 pesa: %lf kg\n",[meuGato2 getPeso]);
            printf("meuGatoFilho pesa: %lf kg\n",[meuGatoFilho getPeso]);
    
            [meuGato free];
            [meuGato2 free];
            [meuGatoFilho free];
    
            return 0;
    }
    Em Objective-C você pode se referir ao próprio objeto que está recebendo a mensagem, usando para isso a palavra “self”. Isso tem muitas utilidades, por exemplo para executar um método que precise executar outros métodos. Um exemplo não muito bom seria criar um método “comer” para o nosso gato que utilizasse o método “setPeso” (como [self setPeso: 5]) para engordá-lo; nesse caso poderíamos alterar o valor de “peso” sem recorrer ao “self”, porém caso tivéssemos algum método que realizasse muitas tarefas isso seria de grande utilidade. Agora uma dica de organização: tipicamente os programadores dividem suas classes em arquivos separados, nomeados “classe.h” e “classe.m”; o primeiro contém a seção “@interface” e o segundo “@implementation”. O arquivo de interface diz ao compilador como a sua classe é, enquanto que o arquivo de implementação contém o código verdadeiro da classe. Para realizar ligar os diversos arquivos devemos compilar o programa de uma forma especial, bem como nos utilizar da diretriz de pré-processamento “#import”. Observe a nova implementação do programa do gato: Gato.h
    //
    // Classe Gato - interface
    // 
    // por Alberto GOK Martins
    // para o tutorial de ObjC
    //
    
    #import 
    
    @interface Gato: Object
    {
            double peso;
    }
    
    -(void) miau;
    -(void) setPeso: (double) p;
    -(double) getPeso;
    -(Gato *) reproduzir: (Gato *) Gato2;
    
    @end
    Gato.m
    //
    // Classe Gato - implementacao
    //
    // por Alberto GOK Martins
    // para o tutorial de Objc
    //
    
    #import 
    #import "Gato.h"
    
    @implementation Gato
    
    -(void) miau
    {
            printf("Miaau!\n");
    }
    
    -(void) setPeso: (double) p
    {
            peso=p;
    }
    
    -(double) getPeso
    {
            return peso;
    }
    
    -(Gato *) reproduzir: (Gato *) Gato2
    {
            // funcao para criar um gato filho com a media dos pesos dos pais
            // antes de algum protesto, nao estamos tentando ser biologicamente corretos!
    
            Gato *Gatinho=[[Gato alloc] init];
            double pesoGatinho;
    
            pesoGatinho = (peso+[Gato2 getPeso])/2;
    
            [Gatinho setPeso: pesoGatinho];
    
            return Gatinho;
    }
    
    @end
    main.m
    //
    // Programa Gato com caracteristica
    // em multiplos arquivos
    //
    // por Alberto GOK Martins
    // para o tutorial de ObjC
    //
    
    #import 
    #import "Gato.h"
    
    int main( int argc, const char *argv[] )
    {
            Gato *meuGato = [[Gato alloc] init];
            Gato *meuGato2 = [[Gato alloc] init];
            Gato *meuGatoFilho;
    
            [meuGato setPeso: 4.2];
            [meuGato2 setPeso: 4.9];
            [meuGato miau];
            [meuGato2 miau];
    
            meuGatoFilho = [meuGato reproduzir: meuGato2];
            [meuGatoFilho miau];
    
            printf("meuGato pesa: %lf kg\n",[meuGato getPeso]);
            printf("meuGato2 pesa: %lf kg\n",[meuGato2 getPeso]);
            printf("meuGatoFilho pesa: %lf kg\n",[meuGatoFilho getPeso]);
    
            [meuGato free];
            [meuGato2 free];
            [meuGatoFilho free];
    
            return 0;
    }
    Preste especial atenção em como a diretiva “#import” é utilizada. O arquivo “Gato.h” precisa de informações sobre a classe “Object” que foi definida no arquivo “objc/Object.h”, e por isso devemos importá-lo em “Gato.h”. Já o arquivo “Gato.m” deve importar o arquivo de interface de sua classe, o “Gato.h”, bem como “stdio.h”, pois utiliza a função “printf”. Finalmente, o programa principal deve importar o arquivo “stdio.h” pela função “printf” e o arquivo “Gato.h” por instanciar objetos da classe “Gato”. Isso pode parecer um pouco confuso, mas na verdade o conceito é bastante simples: deve-se importar tudo o que for utilizar. Para compilar programas com multiplos arquivos no gcc, use a seguinte linha de comando:
    gcc arquivo1.m arquivo2.m main.m -o nome_do_programa -l objc
    no caso do nosso programa, use:
    gcc Gato.m main.m -o gato -l objc
    execute o programa e veja o resultado; ele deve ser similar ao apresentado abaixo:
    Miaau!
    Miaau!
    Miaau!
    meuGato pesa: 4.200000 kg
    meuGato2 pesa: 4.900000 kg
    meuGatoFilho pesa: 4.550000 kg

Herança

    Nesta seção falaremos sobre um dos conceitos mais importantes da programação orientada a objetos: a herança.Uma classe pode ter a si mesma como superclasse, e essa classe, que não possui superclasse é denominada classe raiz (ou root). A classe raiz pode ser programada por você mesmo, ou então como é mais comum, ser a classe Object, descrita em “objc/Object.h” ou a classe NSObject, descrita em “Foundation/NSObject.h”. A classe que foi criada neste tutorial é uma subclasse de Object, e com isso ela herda certos métodos, como free e outros que foram definidos para a classe Object. No entanto suponha que agora seja necessário criar um classe para cachorros. Bem, poderíamos criar uma subclasse de Object denominada Cachorro e implementar funções como setPeso e getPeso idênticas às da classe Gato. Uma solução melhor, seria criar uma subclasse de Object denominada Animal, e as classes Cachorro e Gato seriam subclasses da classe Animal, que por sua vez seria uma classe abstrata, visto que nunca iremos criar uma instância de Animal. No exemplo abaixo fizemos justamente isso. Animal.h
    //
    // Classe Abstrata Animal - interface
    //
    // por Alberto GOK Martins
    // para o tutorial de Objc
    //
    
    #import 
    
    @interface Animal : Object
    {
            double peso;
    }
    
    -(void) setPeso: (double) p;
    -(double) getPeso;
    
    @end
    Animal.m
    //
    // Classe Abstrata Animal - implementacao
    //
    // por Alberto GOK Martins
    // para o tutorial de Objc
    //
    
    #import "Animal.h"
    
    @implementation Animal
    
    -(void) setPeso: (double) p
    {
            peso=p;
    }
    
    -(double) getPeso
    {
            return peso;
    }
    
    @end
    Gato.h
    //
    // Classe Gato - interface
    //
    // por Alberto GOK Martins
    // para o tutorial de Objc
    //
    
    #import "Animal.h"
    
    // aqui comeca a definicao das interfaces
    @interface Gato: Animal
    
    -(void) miau;
    
    @end
    Gato.m
    //
    // Classe Gato - implementacao
    //
    // por Alberto GOK Martins
    // para o tutorial de Objc
    //
    
    #import "Gato.h"
    #import 
    
    // aqui comecam as implementacoes dos metodos
    @implementation Gato
    
    -(void) miau
    {
            printf("Miaau!\n");
    }
    
    @end
    Cachorro.h
    //
    // Classe Cachorro - interface
    //
    // por Alberto GOK Martins
    // para o tutorial de Objc
    //
    
    #import "Animal.h"
    
    // aqui comeca a definicao das interfaces
    @interface Cachorro: Animal
    
    -(void) auau;
    
    @end
    Cachorro.m
    //
    // Classe Cachorro - implementacao
    //
    // por Alberto GOK Martins
    // para o tutorial de Objc
    //
    
    #import "Cachorro.h"
    #import 
    
    // aqui comecam as implementacoes dos metodos
    @implementation Cachorro
    
    -(void) auau
    {
            printf("AuAu!\n");
    }
    
    @end
    main.m
    //
    // Programa de Animais com heranca
    //
    // por Alberto GOK Martins
    // para o tutorial de ObjC
    //
    
    #import 
    #import "Gato.h"
    #import "Cachorro.h"
    
    // aqui comeca o programa
    int main( int argc, const char *argv[] )
    {
            Gato *meuGato = [[Gato alloc] init];
            Gato *meuGato2 = [[Gato alloc] init];
            Cachorro *meuCachorro = [[Cachorro alloc] init];
            Cachorro *meuCachorro2 = [[Cachorro alloc] init];
    
            [meuGato setPeso: 4.2];
            [meuGato2 setPeso: 4.9];
            [meuGato miau];
            [meuGato2 miau];
    
            printf("meuGato pesa: %lf kg\n",[meuGato getPeso]);
            printf("meuGato2 pesa: %lf kg\n",[meuGato2 getPeso]);
    
            [meuCachorro setPeso: 10.2];
            [meuCachorro2 setPeso: 13.3];
            [meuCachorro auau];
            [meuCachorro2 auau];
    
            printf("meuCachorro pesa: %lf kg\n",[meuCachorro getPeso]);
            printf("meuCachorro2 pesa: %lf kg\n",[meuCachorro2 getPeso]);
    
            [meuCachorro free];
            [meuCachorro2 free];
            [meuGato free];
            [meuGato2 free];
    
            return 0;
    }
    Observe que no exemplo acima o método “reproduzir” nao existe mais. Optamos por não escrevê-lo, pois embora essa seja uma atividade comum para todos os animais a reprodução de animais diferentes deve gerar objetos de classes diferentes, e não um animal genérico da classe animal. Para contornar o problema você poderia escrever dois métodos, um para cada classe, denominados “reproduzir”, que embora partilhassem o mesmo nome seriam um pouco diferentes; afinal você não espera que um casal de cachorros gerem filhos gatos. Implementar um método comum exigirá um pouco mais de conhecimento, e isso será realizado na próxima seção, denominada Polimorfismo, Typing dinâmico e Binding dinâmico. Suponha agora que você queira que o método getPeso para um gato retorne o peso em gramas e não em quilos. Bem, você pode modificar a implementação original de getPeso na clase Animal, porém isso modificará também o retorno do getPeso para cachorros. Para solucionar este problema pode-se utilizar um conceito denominado overriding. Overriding é simplesmente sobrescrever um método. Quando você cria um método com o mesmo nome de um outro método que foi herdado pela classe, vale o método da classe e não o da superclasse. Logo, você poderia criar um método dentro da classe Gato com o mesmo nome (no caso, getPeso) e com isso apenas o método da classe Gato seria afetado, permitindo que a classe Cachorro continuasse retornando o peso em kilogramas. Experimente, realizando overriding de getPeso da classe Gato (não esqueça de modificar o printf da rotina main para escrever “g” ao invés de “kg”). Dentro de classes podemos também instanciar objetos. Por exemplo, suponhamos que todos os animais (logo todas as subclasses da classe Animal – novamente, não estamos tentando ser biologicamente corretos!) tenham olhos. Podemos então, definir uma classe denominada Olho, e instanciá-la dentro da classe Animal. Observe a interface e implementação da classe Olho, bem como os novos arquivos da classe Animal. Olho.h
    //
    // Classe Olho - interface
    //
    // por Alberto GOK Martins
    // para o tutorial de Objc
    //
    
    #import 
    
    @interface Olho : Object
    {
            int estado_da_pupila;
    }
    
    -(void) setEstado_Da_Pupila: (int) pupil;
    -(void) printEstado_Da_Pupila;
    
    @end
    Olho.m
    //
    // Classe Olho - implementacao
    //
    // por Alberto GOK Martins
    // para o tutorial de Objc
    //
    
    #import "Olho.h"
    
    @implementation Olho
    
    -(void) setEstado_Da_Pupila: (int) pupil
    {
            if(pupil==0) estado_da_pupila=0;
            if(pupil==1) estado_da_pupila=1;
            if(pupil==2) estado_da_pupila=2;
    }
    
    -(void) printEstado_Da_Pupila
    {
            if(estado_da_pupila==0)
            {
                    printf("A pupila está contraída\n");
            }
            if(estado_da_pupila==1)
            {
                    printf("A pupila está normal\n");
            }
            if(estado_da_pupila==2)
            {
                    printf("A pupila está dilatada\n");
            }
    }
    
    @end
    Animal.h
    //
    // Classe Abstrata Animal - interface
    //
    // por Alberto GOK Martins
    // para o tutorial de Objc
    //
    
    #import 
    #import "Olho.h"
    
    @interface Animal : Object
    {
            double peso;
            Olho *AOlho;
    }
    
    -(void) setPeso: (double) p;
    -(double) getPeso;
    -(void) printEstado_Da_Pupila;
    -(void) setEstado_Da_Pupila: (int) edp;
    
    @end
    Animal.m
    //
    // Classe Abstrata Animal - implementacao
    //
    // por Alberto GOK Martins
    // para o tutorial de Objc
    //
    
    #import "Animal.h"
    
    @implementation Animal
    
    -(void) setPeso: (double) p
    {
            peso=p;
    }
    
    -(double) getPeso
    {
            return peso;
    }
    
    -(void) printEstado_Da_Pupila
    {
            // funcao para imprimir o estado da pupila de um animal
    
            if(AOlho)
                   [AOlho printEstado_Da_Pupila];
            else
                    printf("Não foi definido um estado da pupila deste animal.\n");
    }
    
    -(void) setEstado_Da_Pupila: (int) edp
    {
            [AOlho free];
            AOlho = [[Olho alloc] init];
            [AOlho setEstado_Da_Pupila: edp];
    }
    
    @end
    O código que deve ser utilizado para testar o funcionamento do Olho em main.m é:
    [meuGato setEstado_Da_Pupila: 1];
    [meuGato printEstado_Da_Pupila];
    Obtivemos agora um enorme problema. Como é que vamos liberar a memória alocada para o Olho do Animal? Como não podemos acessar diretamente o objeto AOlho não podemos liberar a memória sem criar um método pertencente à classe Animal específico para isso; ou então, como saída mais inteligente, realizar um overriding do método free. Caso não liberemos a memória teremos um problema que se denomina vazamento de memória, ou memory leakage. Bem, para realizar o overriding de free precisamos saber como liberar a memória alocada pelo próprio objeto, no entanto como o método free é agora diferente do original ele não mais saberá como liberar a memória alocada para o objeto. A saída para isso é a instrução super que se refere a classe pai do recebedor da mensagem. Super chamará não o método da classe atual, mas aquele que foi herdado. Desta forma podemos sempre nos referir ao método antigo de todos os métodos que foram implementados através de overriding. Logo a implementação do método free para a classe Animal deve ser:
    -(id) free
    {
            [AOlho free];
            return [super free];
    }
    Deixaremos para nos preocupar com a palavra id na próxima seção

Polimorfismo, Typing dinâmico e Binding dinâmico

    Polimorfismo é um conceito muito simples. Ele nada mais é do que a habilidade que uma linguagem orientada à objetos tem de definir métodos com o mesmo nome para classes diferentes. Cada definição de classe guarda o código necessário para seus métodos.Typing dinâmico é a característica que a linguagem tem de poder postergar a determinação da classe de um objeto até o tempo de execução do programa, enquanto que Biding dinâmico é poder postergar a determinação do método que será invocado em um objeto até o tempo de execução. Para realizar o typing e o binding dinâmicos utiliza-se o tipo id. Este é um tipo de objeto genérico, que pode ser utilizado para guardar objetos pertencentes a qualquer classe. Na seção anterior utilizamos o tipo id para realizar o overriding do método free. Vejamos agora, como implementar o método reproduzir na classe Animal, e permitir que a classe Gato e Cachorro se reproduzam, sem que seja necessário criar dois métodos distintos:
    -(id) reproduzir: (id) Animal2
    {
            // funcao para criar um animal filho com a media dos pesos dos pais
            // antes de algum protesto, nao estamos tentando ser biologicamente corretos!
            // existe um teste para verificar se os animais sao da mesma classe.
    
            id Filho=[[[self class] alloc] init];
    
            if ([self class] == [Animal2 class])
            {
                    printf("O filho nasceu sadio!\n");
                    [Filho setPeso: (peso+[Animal2 getPeso])/2];
            }
      else
            {
                    printf("O filho nasceu morto, pois os pais são de classes diferentes!\n");
                    [Filho setPeso: 0];
            }
            return Filho;
    
    }
    Na implementação da função acima utilizamos o tipo id, pois não sabemos qual será a subclasse de Animal que será passada nem a classe que irá retornar. Utilizamos também a palavra self que serve para se referir ao próprio objeto, logo dizer [self class] é uma forma de pedir para o objeto retornar a própria classe; no método reproduzir precisamos criar um filho da mesma classe dos pais, logo usamos [self class] como a classe do filho.

Últimas palavras

    Esse tutorial deve ser aprimorado, com o passar do tempo e com sua ajuda. Por favor, não deixe de enviar um email dizendo o que achou, se conseguiu aprender alguma coisa ou se não conseguiu aprendeu nada.Por enquanto é isso. Após essas seções estarem melhor talhadas, pretendo incluir outros tópicos, como C-básico, posing, categorias e a utilização básica do framework Foundation. Entretanto, enquanto esses aprimoramentos não vem, e caso você queira se aprofundar na linguagem eu sugiro os links e referências presentes na seção Referências e links.

Referências e links

Página por Alberto G. O. K. Martins – algol@astro.iag.usp.br
Design based on the Dekorte’s Objective-C webpage. CSS additions by Alberto G. O. K. Martins.
Qualquer contribuição, alteração, comentário ou sugestão, favor enviar para o email algol@astro.iag.usp.br.

quarta-feira, 9 de junho de 2010

Como funciona a nova tela do iPhone 4

Durante a apresentação do iPhone 4, na WWDC 2010 (Conferência anual da Apple), realizada em 7/6, Steve Jobs detalhou que o novo aparelho fará uso do que a Apple chama de “Retina display” (algo como Tela retina).

Mas o que exatamente é uma tela Retina e como ela, junto com outras tecnologias de tela, beneficiam o novo iPhone, mais magro e pronto para HD (alta definição)? Para explicar de forma simples, a nova tela do telefone é um LCD (tela de cristal líquido) que ostenta uma densidade de pixel superalta ao espremer a resolução de 960x640 pixels em 3,5 polegadas – uma densidade de 326 pixels por polegada (ppi). A tela Retina possui quatro vezes o número de pixels dos iPhones anteriores; seu tamanho não mudou, resultando no dobro de densidade de pixels. Em comparação ao modelo 3GS, que possui uma tela de 163ppi com uma resolução de 480 por 320 pixels, é fácil imaginar como essa nova tela vai brilhar.


retina1.jpg
Imagem close-up da tela do iPhone 4, que possui uma resolução superalta

Enquanto falava sobre a nova tela, Steve Jobs detalhou que após um certo ponto o olho humano falha em distinguir pixels individuais. De acordo com o CEO da Apple, esse “número mágico”, quando não existe mais pixelização visível, está próximo de 300 ppi. Dessa maneira, com a tela do iPhone 4 vindo com 326 ppi, sua imagem supostamente sempre vai ter um visual suave e uniforme.


retina2.jpg
Em comparação, o mesmo ícone na tela do iPhone 3GS apresenta pixelização

As fotos deste artigo matéria (acima), feitas pela editora sênior da PC World americana, Melissa Perenson, mostram um ícone de uma tela do iPhone 4 em comparação ao mesmo ícone no 3GS. A diferença, como você pode ver, é bem evidente.
A companhia ainda afirma que a tela do iPhone 4 terá uma proporção de contraste (contrast ratio) quatro vezes maior do que os modelos anteriores. Além do uso de mais pixels compactos, a tela, que é uma backlit LED, também vai adotar a tecnologia IPS (In-Plane Switching), presente no iPad, para melhorar os ângulos de visão e a exibição de cores.
A Apple não é a primeira a colocar uma tela de resolução superalta em um smartphone. O Nexus One, do Google, por exemplo, possui uma tela OLED (Organic light-emitting diode) com uma resolução de 800 x 480 pixels.





fonte: http://macworldbrasil.uol.com.br

segunda-feira, 24 de maio de 2010

Dropbox - A melhor opçao de Computaçao nas Nuvens

Nuvem, nuvem, nuvem… Muito se fala da tal cloud computing, mas quais programas para usuários finais que você conhece já fazem uso desse conceito com efetividade? Um deles é, sem dúvida alguma, o Dropbox.
O programa, com clientes para Windows, Linux e Mac OS X, além de iphone e Android, numa definição simples é um HD virtual. Além de fazer a sincronia entre tantos computadores quantos o usuário queira, o serviço ainda espelha os arquivos na Internet, com direito até a salvamento de versões.


O Dropbox ainda contém um lado social, no qual permite o compartilhamento de pastas entre dois ou mais usuários do serviço, com opções para isso ao alcance do mouse, no menu de contexto dos arquivos e pastas.
Na modalidade gratuita, o Dropbox oferece 2 GB de espaço, com a possibilidade de ir até 10 GB, via indicações de novos usuários. Para quem precisa de mais espaço e tem disponibilidade de pagar, existem planos de 50 e 100 GB, ao custo de US$ 9,99 e US$ 19,99 ao mês, respectivamente.
  • Nome? Dropbox
  • Para que serve? Serviço de sincronia de arquivos entre PCs e backup de arquivos na nuvem.
  • Ponto forte? Funciona como se espera, tem planos generosos de espaço e formas de aumentá-lo mesmo na conta gratuita, e é multiplataforma.
  • Ponto fraco? Só permite sincronizar uma única pastas, definida pelo próprio programa. Parece que esse comportamento mudará na próxima versão, mas enquanto isso…
  • Licença? Freeware (2~10 GB de espaço)
  • Tamanho? variável (depende do sistema)
  • Site oficial/Download
 fonte: http://meiobit.com/

sexta-feira, 14 de maio de 2010

Entenda por que o iPhone ainda não é ameaçado pelo Android

Esta semana, um ‘estudo’ indicou que o Android teria finalmente passado o iPhone no número de vendas nos Estados Unidos, o que fez com que pessoas mal informadas já decretassem o fim da supremacia da Apple, como era costume da imprensa na década de 90. Mas entenda por que um pouquinho de boa vontade e discernimento é suficiente para concluir que ainda é muito precipitado afirmar que o iPhone chegou ao fim.


Na última segunda-feira, a empresa NPD Group publicou o resultado de uma pesquisa que afirma que as vendas de Android teriam ultrapassado, pela primeira vez na história, aquelas do iPhone no território norte-americano. Esta pesquisa, segundo a própria página do grupo, é baseada em (apenas) 150.000 inquéritos onlines com clientes. Ou seja, o resultado apresentado na verdade é uma tendência estatística e não números concretos de vendas.
Justamente por isso, a Apple se pronunciou oficialmente ontem, através de sua porta-voz, alegando que a pesquisa foi feita com um número muito limitado de consumidores. Além disso, ressaltou o recorde de vendas do iPhone no último ano, com aumento de 130%.
Mas vamos imaginar que, mesmo com todos estes pontos dúbios da pesquisa, o Android realmente tenha vendido mais. Isso seria o fim da ‘era iPhone‘? (sic)
Quem afirma isto provavelmente está muito mal informado. Para começar, a operadora Verizon (concorrente da AT&T nos EUA) fez no último mês uma promoção de “Pague um e leve dois celulares”, em toda a sua linha de produtos, inclusive os com Android. Só isso seria o suficiente para aumentar o número de aparelhos “vendidos” de qualquer celular, mesmo que o faturamento tenha sido apenas da metade.
Além disso, há outros fatores de mercado que fazem com que, naturalmente, as vendas do iPhone tenham uma queda nesta época do ano. Um deles é o lançamento recente do iPad.
É normal que o consumidor que estava querendo comprar um celular novo, mas se encantou com o iPad, compre o tablet e espere um pouco mais para comprar um iPhone. Aqui mesmo alguns leitores já declararam que se o iPad vir junto com o iPhone 4 para o Brasil, terão que escolher um dos dois. Ou seja, não é um desgaste do produto e sim uma imposição econômica.
Outro fator que ajuda na diminuição das vendas por esta época: o lançamento iminente da próxima geração do iPhone. Quem aqui compraria um aparelho hoje sabendo que daqui a um mês vai ser lançado um bem melhor, pelo mesmo preço? É assim que os americanos estão se sentindo no momento: esperando o novo iPhone. Até porque os vários vazamentos comprovam que as melhorias serão boas.
Quero deixar claro que não pretendo aqui menosprezar os celulares com Android. Eles, assim como o iPhone, suprem as necessidades do seu público e por isso não é questão de dizer qual é o melhor ou pior. Mas é importante se informar sobre os reais fatos do mercado antes de publicar sentenças, porque depois que o iPhone 4 vier e fizer mais sucesso ainda, não adianta nada espernear. ;)

Felizmente, mais gente concorda com essa opinião. :)


fonte: http://blogdoiphone.com

segunda-feira, 10 de maio de 2010

Android ultrapassa Apple

Segundo um estudo publicado pela NPD, os smartphones Android ultrapassaram pela primeira vez o iPhone, por 7% nos Estados Unidos e, ao continuar assim, podem vir a ultrapassar a RIM, líder do segmento.



Observando a imagem, podemos ver que o primeiro trimestre de 2010 foi muito positivo para a Google e o seu Android. Temos a RIM que continua a cair, mas não tão acentuadamente como no último trimestre de 2009. Temos a Apple que estagnou em relação ao último trimestre de 2009. Temos ainda as quedas do Windows Mobile e da Palm, recentemente adquirida pela HP. 

Neste momento temos no pódio:
  • RIM -  36%
  • Android – 28%
  • iPhone OS – 21%
O grande vencedor é sem dúvida, o Android, pois o fato de saírem novos smartphones com esta plataforma todos os meses, ajuda imenso a sua propagação.
Existem algumas conclusões a retirar deste estudo:
Por um lado, o fato da Apple estar ao que tudo indica, a preparar uma nova geração de iPhones para Junho, pode ser a razão para a Apple ter estagnado. Além disso, nem podemos comparar a quantidade de smartphones com Android com os iPhones, por isso é mais que normal que o Android continue a subir.
Em relação à RIM, o novo Sistema Operacional que a fabricante apresentou pode vir dar um novo alento, impedindo assim a subida vertiginosa do Android.
Quanto ao Windows Mobile e o Palm WebOS, vamos esperar pelo Windows Phone 7 e veremos também o que a HP faz do WebOS, pois estão também a perder terreno.

sábado, 8 de maio de 2010

Dica Android: Mudar a Homepage do Browser

*Atendendo o pedido do nosso leitor João Piauhy  feito pelo twitter


Todos os novos aparelhos que adquirimos devem ser experimentados para que possamos saber o que podem ou não fazer. Devemos ainda aprender as suas mais básicas funcionalidades para que possamos fazer com eles o que pretendemos.
Por isso Seal System vai dando dicas para ajudar no dia a dia. E que esperamos serem úteis.
Hoje vamos ensinar como mudar a página de abertura do browser num Android.


Com certeza de que para a maioria de vocêss esta dica é desnecessária e provavelmente até já a alteraram. Mas existem de certeza muitos leitores que vão ficar agradecidos com o que vamos ensinar.
Mas passemos então à dica. Para alterarem a página iniciar do browser que acompanha o Android.
Para iniciarmos o processo de alteração é necessário que abram o browser.


Depois de terem aberta a página que têm definida como sendo a de abertura devem carregar na tecla de Menu.


Depois de carregarem na tecla Menu deve ser mostrado um novo menu. Ai escolham More. E as opções do browser serão apresentadas.


Dentro das opções do browser devem fazer scroll até à opção Set home page. Selecionem e uma nova caixa será mostrada
.

Nessa caixa devem então definir qual a página que querem que o browser abra sempre que o chamarem ou quando abrirem uma nova janela do browser.
Coloquem o endereço que pretendem e carreguem em OK.

 


E pronto. É tão simples como parece.  Passam a ter como página de exibição no browser o endereço que definiram.
Aconselho a guardarem o endereço que tinham pois não existe maneira de reverter para o endereço antigo.  Caso não o tenham guardado provavelmente será o endereço do Google e podem sempre colocar http://www.google.com.br e ele percebe que vêm de um dispositivo móvel e adapta a página ao seu equipamento.

Espero que tenham gostado!!!