Programação Orientada a Objectos (OOP) - Parte 2: ObjC Jorge C. S. Cardoso, Luís Gustavo Martins jorgecardoso@ieee.org, lmartins@porto.ucp.pt Cursos de Verão na Católica 2010
Classe Veículo em ObjC Divisão do código em  duas partes : Interface declarada num ficheiro  Veiculo.h Implementação definida num ficheiro  Veiculo.m http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
Classe Veículo em ObjC Interface  - Veiculo.h O ObjC &quot;obriga&quot; ao uso de getters e setters      --> Encapsulamento! #import <Foundation/Foundation.h> @interface  Veiculo : NSObject {      // instance variables        int velMax;      int velActual;      int numRodas;      int numLugares; } //setters and getters - (void) setVelMax: (int)vel; - (int)  velMax; - (void) setVelActual: (int)vel; - (int)  velActual; - (void) setNumRodas: (int)numRodas; - (int)  numRodas; - (void) setNumLugares: (int)numLugares; - (int)  numLugares; // other method declarations - (void) arrancar; - (void) travar; - (void) acelerar; - (void) buzinar; - (BOOL) estaParado; - (void) mostrarEstado; @end
Classe Veículo em ObjC Implementação  - Veiculo.m #import &quot;Veiculo.h&quot; @implementation  Veiculo  //setter and getters -(int)velMax {      return velMax; } -(void) setVelMax: (int)vel {      velMax = vel; } //... similar for other setter/getters //other methods -(void) arrancar {      //implementação do método arrancar... } -(void) travar {      // ... } //... other methods... @end Implementar setters/getters Implementar métodos Getters e setters podem ser criados automaticamente...      -  properties      -  synthesize
Classe Veículo em ObjC Uso de Properties e Synthesized Getters e Setters #import <Foundation/Foundation.h> @interface  Veiculo : NSObject {      // instance variables        int velMax;      int velActual;      int numRodas;      int numLugares; } //setters and getters - (void) setVelMax: (int)vel; - (int)  velMax; - (void) setVelActual: (int)vel; - (int)  velActual; - (void) setNumRodas: (int)numRodas; - (int)  numRodas; - (void) setNumLugares: (int)numLugares; - (int)  numLugares; // other method declarations - (void) arrancar; - (void) travar; - (void) acelerar; - (void) buzinar; - (BOOL) estaParado; - (void) mostrarEstado; @end #import <Foundation/Foundation.h> @interface  Veiculo : NSObject {      // instance variables        int velMax;      int velActual;      int numRodas;      int numLugares; } //properties @property velMax; @property velActual; @property numRodas, numLugares; // other method declarations - (void) arrancar; - (void) travar; - (void) acelerar; - (void) buzinar; - (BOOL) estaParado; - (void) mostrarEstado; @end
Classe Veículo em ObjC Uso de Properties e Synthesized Getters e Setters #import &quot;Veiculo.h&quot; @implementation Veiculo  //setter and getters -(int)velMax {      return velMax; } -(void) setVelMax: (int)vel {      velMax = vel; } //... similar for other setter/getters //other methods -(void) arrancar {      //implementação do método arrancar... } -(void) travar {      // ... } //... other methods... @end #import &quot;Veiculo.h&quot; @implementation  Veiculo  //synthesized setter and getters @synthesize velMax; @synthesize velActual: @synthesize numRodas; @synthesize numLugares; //other methods -(void) arrancar {      //implementação do método arrancar... } -(void) travar {      // ... } //... other methods... @end
Classe Veículo em ObjC Uso de Properties e Synthesized Getters e Setters É possível alterar o comportamento do setter sintetizado para uma variável membra, usando modificadores Num setter do tipo:      -(void) setVar: (SomeClass *)value Se o sintetizarmos com os seguintes modificadores, teremos  no corpo do setter (sintetizado)  as seguintes atribuições:      @property (assign) var       var = value; //simple assignation    @property (retain) var           var = [value retain]; //assignation with reference counter increment    @property (copy) var      var = [value copy]; //object is copied (must conform to the NSCopying protocol...)
Herança em ObjC O ObjC suporta herança simples ou seja, uma classe apenas pode herdar de uma classe pai Tal como o Java (outras linguagens, como o C++, suportam herança múltipla) Em vez de herança multipla, o ObjC suposta o uso de &quot; categories &quot; e &quot; protocols &quot; (semelhantes às &quot;interfaces&quot; do Java) http://developer.apple.com/iphone/library/documentation/cocoa/conceptual/objectivec/Articles/ocCategories.html http://developer.apple.com/iphone/library/documentation/cocoa/conceptual/objectivec/Articles/ocProtocols.html#//apple_ref/doc/uid/TP30001163-CH15-SW1 NSObject  • Root class  • Implements many basics  ■ Memory management  ■ Introspection  ■ Object equality http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
ObjC: Métodos de Classe e de Instância Instâncias respondem a métodos de instância:      - (id)   init;      - (void) setVelMax: (int) vel;          - (int)  velMax;      - (void) travar;      ... Classes respondem a métodos de classe:      + (id) alloc;      + (id) Veiculo;      + (Veiculo *) sharedVeiculo;      ...
ObjC: Mensagens para Objectos Em ObjC, em vez de se &quot;chamar&quot; métodos de objectos (como em Java ou C++),  enviam-se &quot;mensagens&quot;  Sintaxe:       [receiver  message ]          [receiver  message: argument]       [receiver  message: arg1  andArg: arg2]      Exemplos:      Veiculo *meuVeiculo; //assume this exists... [meuVeiculo trava]; [meuVeiculo setVelMax:300] //you wish!! ;-) [meuVeiculo vira:90 andPiscaPisca:YES]; int speed = [meuVeiculo velActual];
ObjC: Mensagens para Objectos O  &quot;Dot-Syntax &quot; O ObjC 2.0 introduziu uma  outra forma de se aceder a variáveis membras de um objecto O dot-syntax faz uso dos setters e getters!! Não quebra o ENCAPSULAMENTO!! Veiculo *meuVeiculo; //assume this exists... int speed1 = [meuVeiculo velActual];  //message int speed2 = meuVeiculo . velActual;  //dot syntax [meuVeiculo setVelActual: 120]; //message meuVeiculo.velActual = 60; //dot syntax
ObjC: Mensagens para Objectos O  &quot;Dot-Syntax &quot;  - Um problema frequente... O que é que acontece quando o seguinte código executa? @implementation Person           - (void)setAge:(int)newAge { //setter              self.age =  newAge; //age é uma variável membra          }          @end É equivalente a:          @implementation Person           - (void)setAge:(int)newAge { //setter              [self setAge:newAge] ;  // Infinite loop!           }          @end
ObjC:  self  e  super self  - mensagens para o próprio Objecto super  - mensagens para o &quot;pai&quot; do Objecto #import &quot;Veiculo.h&quot; @implementation Veiculo -(BOOL) isFamilyVehicle {      return ([self numLugares] >= 4); } //other method implementations... -(void) doSomething {      //call superclass implementation first...      [super doSomething];           //now do our own stuff...      int foo = bar;      //...  }
ObjC: tipos dinâmicos e est´ticos Objectos com tipos dinâmicos id anObject;  apenas  id  e não  id* a não ser que se saiba o que se está a fazer... tipo genérico : pode ser usado para apontar para qualquer objecto Objectos com tipos estáticos Veiculo *meuVeiculo; O ObjC implementa verificação de tipos em  compile-time  (e não em  run-time ) O ObjC usa sempre  &quot;dynamic binding&quot;  
ObjC: ciclo de vida de objectos Criação de Objectos   Processo de dois passos:   alocar memória para o objecto:  +alloc   inicializar o estado do objecto:  -init Construtor Veiculo *meuVeiculo = nil; meuVeiculo =  [[Veiculo alloc] init] ; #import &quot;Veiculo.h&quot;  @implementation Veiculo  - (id)init  {       // allow superclass to initialize its state first       if ( self  = [ super   init ]) {          velMax = 120;          velActual = 0;          numRodas = 4;          numLugares = 4;      }       return  self ; }  @end
ObjC: ciclo de vida de objectos Criação de Objectos - Métodos  init  (construtores)   Uma classe pode definir múltiplos métods  init -(id) init;  -(id) initWithVelMax:(int) vel;  -(id) initWithVelMax:(int) vel velActual:(int) vel; ... Métodos menos específicos chamam tipicamente métodos mais específicos usando valores por omissão: -(id)  init  {return  [self initWithVelMax: 120] ;} -(id)  initWithVelMax :(int) vel {      return  [self initWithVelMax:vel velActual:0] ; }
ObjC: ciclo de vida de objectos Destruição de Objectos   Depois de criado com com  alloc  (normalmente seguido de  init ), e no caso de não mais ser necessário,  um objecto deve ser &quot;limpo&quot; da memória!   Para cada alloc deverá haver um dealloc   caso contrário criam-se &quot; fugas de memória &quot;!! No entanto,  d ealloc   nunca  é chamado directamente !   com uma excepção (ver mais à frente...)   existe um mecanismo para &quot;desalocar&quot; sem chamar  dealloc  ...   REFERENCE COUNTING
ObjC: ciclo de vida de objectos Destruição de Objectos   REFERENCE COUNTING Todos os objectos implementam um  &quot;retain count&quot; Herdado de  NSObject enquanto o &quot;retain count&quot; > 0, objectivo é mantido em memória e válido +alloc  e  -copy  criam objectos com &quot;retain count&quot; == 1 -retain  incrementa o &quot;retain count&quot; -release  decrementa o &quot;retain count&quot; Quando o &quot;retain count&quot; atinge o valor 0 o objecto é destruído! -dealloc  é chamado automaticamente Ponto de não retorno!
ObjC: ciclo de vida de objectos Destruição de Objectos  -  REFERENCE COUNTING http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
ObjC: ciclo de vida de objectos Destruição de Objectos   Veiculo *meuVeiculo = nil; meuVeiculo = [[Veiculo alloc] init]; [meuVeiculo setVelMax:120]; [meuVeiculo arranca]; [meuVeículo setVelActual: 50]; //... [meuVeiculo para];  //no more need for this object... [meuVeiculo release]; //meuVeiculo will be destroyed in case its retain //count is zero (i.e. no one else is pointing to it) //And in that case, sending messages to it will CRASH! [meuVeiculo arranca];//CRASH!!
ObjC: ciclo de vida de objectos Destruição de Objectos   Veiculo *meuVeiculo = nil; meuVeiculo = [[Veiculo alloc] init]; [meuVeiculo setVelMax:120]; [meuVeiculo arranca]; [meuVeículo setVelActual: 50]; //... [meuVeiculo para];  //no more need for this object... [meuVeiculo release]; meuVeiculo = nil; //good programming practice! [meuVeiculo arranca];//No longer crashes!:-) No effect...
ObjC: ciclo de vida de objectos Destruição de Objectos - Destrutor Implementação do método  -dealloc   #import &quot;Veiculo.h&quot; @implementation Veiculo -dealloc { //this is an override of NSObject dealloc      //do any cleanup that is necessary...      //...      //when done, ask super to also clean itself up      [super dealloc]; //only time you call dealloc explicitly! } //other method implementations... @end
ObjC: a classe  NSString  Suporte genérico para strings Unicode Unicode é um sistema de codificação de caracteres que suporta todas as linguagens do mundo Consistentemente usada na API Cocoa e Cocoa Touch em prejuízo das C-strings (i.e.  char * ) sem dúvida uma das classes mais usadas em Cocoa Em ObjC, &quot;constant strings&quot; são definidas como:      @“just as simple” E &quot;constant strings&quot; são na realidade instâncias de  NSString                              NSString *aString = @”Hello World!”;
ObjC: a classe  NSString Formatação de Strings Semelhante ao usado em Java e C++ (e.g.  printf ) %d  - para  int s %f   - para  float s %c  - para  char s etc... %@  - para objectos!! --> ObjC          NSString *aString = @”Johnny”;          NSString *log = [NSString stringWithFormat: @”It’s ‘%@’”, aString];          //log would have been set to: &quot;It’s ‘Johnny’&quot;            NSLog(@”I am a %@, I have %d items”, [array className], [array count]);          //Would print: &quot;I am a NSArray, I have 5 items&quot;
ObjC: apontadores nulos -  nil Apontadores em ObjC podem ser nulos:          int *numberPtr = nil; Testando um apontador nulo, explicitamente:          if (numberPtr == nil) {return;} Testando um apontador nulo, implicitamente:          if (!numberPtr) {return;} Podem ser usados em atribuições ou argumentos:          numberPtr = nil;          [myCalculator setValue: nil]; Pode-se enviar mensagens para  nil  (são ignoradas...):          myObject = nil;          [myObject doSomething];
ObjC:  Identidade versus Igualdade entre Objectos Identidade Teste da  igualdade dos respectivos apontadores &quot;É o mesmo Objecto?&quot;      if ( object1 == object2 ) {NSLog(@&quot;Same exact object instance&quot;);} Igualdade Teste da  igualdade dos atributos  (i.e. variáveis membras de cada objecto) &quot;Os Objectos têm o mesmo conteudo?&quot;       if ( [object1 isEqual: object2] ) {          NSLog(@&quot;Logically equivalent,                   but may be different object instances&quot;);      }
ObjC: reponsabilidade pela vida de Objectos #import <Foundation/Foundation.h>  @interface Veiculo : NSObject {      // instance variables       NSString *marca; //Veiculo class “owns” the NSString object 'marca'        int velMax;      //...  }  // method declarations - (void)init;  - (NSString *)marca;  - (void)setMarca:(NSString *)novaMarca;  - (int)velMax; - (void)setVelMax:(int)vel; //...  @end
ObjC: reponsabilidade pela vida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  - (id)init  {       // allow superclass to initialize its state first       if (self = [super init]) {          marca = @&quot;não definida&quot;; //this is a NSString          velMax = 120;          velActual = 0;          numRodas = 4;          numLugares = 4;      }       return self; } //other method implementations...   @end
ObjC: reponsabilidade pela vida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  - (NSString *)marca { return marca;}  - (void)setMarca:(NSString *)novaMarca {       marca = novaMarca; //!!! memory leak!! }  @end Se  marca  apontasse para uma  NSString  já existente (e.g. alocada no construtor  init  da classe Veiculo) essa zona de memória ficaria &quot;em fuga&quot;... Setter para um objecto criado pelo nosso objecto Solução 1 (errada)
ObjC: reponsabilidade pela vida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  - (NSString *)marca { return marca;}  - (void)setMarca:(NSString *)novaMarca {       [marca release]; //what if marca == novaMarca?!?      marca = novaMarca; }  @end Se por acaso  novaMarca  apontasse para a mesma  NSString  que  marca  aponta (pode acontecer!!), ao fazer  release  do apontador  marca  correria-se o risco de o  retain counter  cair para zero, e a  NSString  ser destruida!! perder-se-ia a  string  que se pretendia usar para passar para o nosso objecto!! Setter para um objecto criado pelo nosso objecto Solução 2 (ainda errada)
ObjC: reponsabilidade pela vida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  - (NSString *)marca { return marca;}  - (void)setMarca:(NSString *)novaMarca {      if ( marca != novaMarca )       {           [marca release];          marca = [novaMarca retain];           // marca’s retain count has been bumped up by 1      } }  @end Antes de tudo verifica-se se por acaso não estamos a receber um apontador para um objecto NSString para o qual já estamos a apontar Caso não seja, liberta-se o objecto anterior e aponta-se para o que é passado como argumento Setter para um objecto criado pelo nosso objecto Solução 3a (CORRECTA!)
ObjC: reponsabilidade pela vida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  - (NSString *)marca { return marca;}  - (void)setMarca:(NSString *)novaMarca {      if ( marca != novaMarca )       {           [marca release];          marca = [novaMarca copy];           // marca’s retain count has been bumped up by 1      } }  @end Neste caso não copiamos apenas o apontador... É criada uma cópia do objecto!! Evita que alterações na string por alguém que partilhe apontadores para a &quot;nossa&quot;  NSString marca Na realidade, como o objecto  NSString  é  imutável , esse problema não se coloca...  Setter para um objecto criado pelo nosso objecto Solução 3b (CORRECTA!)
ObjC: reponsabilidade pela vida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  //... -(void) dealloc  {      //do any clean up that is needed...          [marca release];      //ask super to do its own clean up      [super dealloc];  }  @end Se alocamos... temos de &quot;desalocar&quot;!! Caso contrário provocamos uma  &quot;fuga de memória&quot; (memory leak) Oh Yeah! Embrace the power!! ;-)
ObjC: reponsabilidade pela vida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  //... -(NSString *) descricao  {       NSString *descricao ;      descricao  = [ [NSString alloc]  initWithFormat:@&quot;Veículo de %d rodas,                  com %d lugares...&quot;, [self numRodas], [self numLugares]);      //remember: [NSString alloc] above bumps the retain count (i.e. +1)!       return descricao ;     }  @end Retornar um objecto... ERRADO! fuga de memória! [NSString alloc]  incrementa o  retain count ... Mas em lado algum é feito o correspondente  release !
ObjC: reponsabilidade pela vida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  //... -(NSString *) descricao  {       NSString *descricao ;      descricao  = [ [NSString alloc]  initWithFormat:@&quot;Veículo de %d rodas,                  com %d lugares...&quot;, [self numRodas], [self numLugares]);      //remember: [NSString alloc] above bumps the retain count (i.e. +1)!      [descricao release]; //will this fix the memory leak? Yes... but we return bogus... :-\      return descricao ;     }  @end Retornar um objecto... ERRADO! Retorna um apontador para um objecto inválido! [NSString alloc]  incrementa o  retain count ... O  release  decrementa-o para zero dealloc  é chamado... objecto é destruído Como resolver?!?!
ObjC: reponsabilidade pela vida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  //... -(NSString *) descricao  {       NSString *descricao ;      descricao  = [ [NSString alloc]  initWithFormat:@&quot;Veículo de %d rodas,                  com %d lugares...&quot;, [self numRodas], [self numLugares]);      //remember: [NSString alloc] above bumps the retain count (i.e. +1)!      [descricao autorelease]; //nice! ;-)      return descricao ;     }  @end Retornar um objecto... CORRECTO! É  feito o  release  ao objecto, mas não imediatamente... Dá-se assim tempo ao código que chamou o método de receber o apontador para um objecto que (ainda é válido!) e de logo a seguir  fazer um  retain   Quando é então feito o &quot;autorelease&quot;??!
ObjC: reponsabilidade pela vida de Objectos O  autorelease  de Objectos chamando  -autorelease  &quot;marca&quot; um objecto para ser enviado um  release  num momento futuro...  Cumpre-se com o requisito de &quot;emparelhar&quot; cada alloc com um release Dando algum tempo ao objecto para sobreviver Forma conveniente de gerir memória muito útil em métodos que retornam objectos!
ObjC: reponsabilidade pela vida de Objectos O  autorelease  e nomes de métodos Métodos cujos nomes comecem por  alloc, copy  ou  new   devolvem (i.e. retornam) objectos com retain count == 1 É necessário fazer  release  quando o objecto não for mais necessário!!   Todos os outros métodos devolvem (i.e. retornam) objectos  autoreleased  (é apenas uma convenção!!) NSMutableString *string = [[NSMutableString alloc] init];  // We are responsible for calling -release or -autorelease  [string autorelease]; NSMutableString *string = [NSMutableString string];  // The method name doesn’t indicate that we need to release it  // So don’t- we’re cool!
ObjC: reponsabilidade pela vida de Objectos Como funciona o  autorelease? Objectos são adicionados a um  &quot;autorelease pool&quot; Este &quot;autorelease pool&quot; monitoriza objectos &quot;marcados&quot; para serem libertados (i.e.  release d) Quando a própria  &quot;autorelease pool&quot;  é libertada, todos os objectos por ela monitorizados são também libertados (i.e.  release d) Quando é a &quot;autorelease pool&quot; libertada??
ObjC: reponsabilidade pela vida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
ObjC: reponsabilidade pela vida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
ObjC: reponsabilidade pela vida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
ObjC: reponsabilidade pela vida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
ObjC: reponsabilidade pela vida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
ObjC: reponsabilidade pela vida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
ObjC: reponsabilidade pela vida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
ObjC: reponsabilidade pela vida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
ObjC: reponsabilidade pela vida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
ObjC: reponsabilidade pela vida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
ObjC: reponsabilidade pela vida de Objectos E não se corre o risco de  &quot;a qualquer momento&quot;  um objecto criado com  autorelease  com ficar inválido e não poder usar um apontador para ele?? Nesse caso, há que fazer  retain ! name = [NSMutableString string]; //autoreleased // We want to name to remain valid!  [name retain];  // ... // Eventually, we’ll release it (maybe in our -dealloc?)  [name release]; NOTA:  autorelease  não é Garbage Collection!! 
Exercício: Classe Calculator e Fraction Implementar em ObjC uma classe Fraction: armazena fracções (i.e. numerador / denominador) imprime a fracção para a consola realiza operações (+, -, *, /) entre fracções #import <Foundation/Foundation.h> #import &quot;Fraction.h&quot; int main (int argc, const char * argv[]) {          NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Fraction *frac1 = [[Fraction alloc] init];          Fraction *frac2 = [[Fraction alloc] init]; [frac1  setTo:  1  over:  3]; [frac1 print]; //print to console something like &quot;1/3&quot;          [frac2  setTo:  5  over:  4];          Fraction* result = [frac1 add: frac2]; //adds two fractions          [result print]; [frac1 release];          [frac2 release];          [result release] [pool drain]; return 0; }
Fim Cursos de Verão na Católica 2010 http://porto.ucp.pt/cvc/ Jorge C. S. Cardoso, Luís Gustavo Martins jorgecardoso@ieee.org, lmartins@porto.ucp.pt http://slideshare.net/jorgecardoso (tag: cvc2010) Código fonte:  http://db.tt/AOFOfA2

OOP ObjC

  • 1.
    Programação Orientada aObjectos (OOP) - Parte 2: ObjC Jorge C. S. Cardoso, Luís Gustavo Martins jorgecardoso@ieee.org, lmartins@porto.ucp.pt Cursos de Verão na Católica 2010
  • 2.
    Classe Veículo emObjC Divisão do código em duas partes : Interface declarada num ficheiro Veiculo.h Implementação definida num ficheiro Veiculo.m http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  • 3.
    Classe Veículo emObjC Interface - Veiculo.h O ObjC &quot;obriga&quot; ao uso de getters e setters      --> Encapsulamento! #import <Foundation/Foundation.h> @interface  Veiculo : NSObject {      // instance variables        int velMax;      int velActual;      int numRodas;      int numLugares; } //setters and getters - (void) setVelMax: (int)vel; - (int)  velMax; - (void) setVelActual: (int)vel; - (int)  velActual; - (void) setNumRodas: (int)numRodas; - (int)  numRodas; - (void) setNumLugares: (int)numLugares; - (int)  numLugares; // other method declarations - (void) arrancar; - (void) travar; - (void) acelerar; - (void) buzinar; - (BOOL) estaParado; - (void) mostrarEstado; @end
  • 4.
    Classe Veículo emObjC Implementação - Veiculo.m #import &quot;Veiculo.h&quot; @implementation Veiculo  //setter and getters -(int)velMax {      return velMax; } -(void) setVelMax: (int)vel {      velMax = vel; } //... similar for other setter/getters //other methods -(void) arrancar {      //implementação do método arrancar... } -(void) travar {      // ... } //... other methods... @end Implementar setters/getters Implementar métodos Getters e setters podem ser criados automaticamente...      - properties      - synthesize
  • 5.
    Classe Veículo emObjC Uso de Properties e Synthesized Getters e Setters #import <Foundation/Foundation.h> @interface  Veiculo : NSObject {      // instance variables        int velMax;      int velActual;      int numRodas;      int numLugares; } //setters and getters - (void) setVelMax: (int)vel; - (int)  velMax; - (void) setVelActual: (int)vel; - (int)  velActual; - (void) setNumRodas: (int)numRodas; - (int)  numRodas; - (void) setNumLugares: (int)numLugares; - (int)  numLugares; // other method declarations - (void) arrancar; - (void) travar; - (void) acelerar; - (void) buzinar; - (BOOL) estaParado; - (void) mostrarEstado; @end #import <Foundation/Foundation.h> @interface  Veiculo : NSObject {      // instance variables        int velMax;      int velActual;      int numRodas;      int numLugares; } //properties @property velMax; @property velActual; @property numRodas, numLugares; // other method declarations - (void) arrancar; - (void) travar; - (void) acelerar; - (void) buzinar; - (BOOL) estaParado; - (void) mostrarEstado; @end
  • 6.
    Classe Veículo emObjC Uso de Properties e Synthesized Getters e Setters #import &quot;Veiculo.h&quot; @implementation Veiculo  //setter and getters -(int)velMax {      return velMax; } -(void) setVelMax: (int)vel {      velMax = vel; } //... similar for other setter/getters //other methods -(void) arrancar {      //implementação do método arrancar... } -(void) travar {      // ... } //... other methods... @end #import &quot;Veiculo.h&quot; @implementation  Veiculo  //synthesized setter and getters @synthesize velMax; @synthesize velActual: @synthesize numRodas; @synthesize numLugares; //other methods -(void) arrancar {      //implementação do método arrancar... } -(void) travar {      // ... } //... other methods... @end
  • 7.
    Classe Veículo emObjC Uso de Properties e Synthesized Getters e Setters É possível alterar o comportamento do setter sintetizado para uma variável membra, usando modificadores Num setter do tipo:      -(void) setVar: (SomeClass *)value Se o sintetizarmos com os seguintes modificadores, teremos no corpo do setter (sintetizado) as seguintes atribuições:      @property (assign) var       var = value; //simple assignation    @property (retain) var           var = [value retain]; //assignation with reference counter increment    @property (copy) var      var = [value copy]; //object is copied (must conform to the NSCopying protocol...)
  • 8.
    Herança em ObjCO ObjC suporta herança simples ou seja, uma classe apenas pode herdar de uma classe pai Tal como o Java (outras linguagens, como o C++, suportam herança múltipla) Em vez de herança multipla, o ObjC suposta o uso de &quot; categories &quot; e &quot; protocols &quot; (semelhantes às &quot;interfaces&quot; do Java) http://developer.apple.com/iphone/library/documentation/cocoa/conceptual/objectivec/Articles/ocCategories.html http://developer.apple.com/iphone/library/documentation/cocoa/conceptual/objectivec/Articles/ocProtocols.html#//apple_ref/doc/uid/TP30001163-CH15-SW1 NSObject  • Root class  • Implements many basics  ■ Memory management  ■ Introspection  ■ Object equality http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  • 9.
    ObjC: Métodos deClasse e de Instância Instâncias respondem a métodos de instância:      - (id)   init;      - (void) setVelMax: (int) vel;          - (int)  velMax;      - (void) travar;      ... Classes respondem a métodos de classe:      + (id) alloc;      + (id) Veiculo;      + (Veiculo *) sharedVeiculo;      ...
  • 10.
    ObjC: Mensagens paraObjectos Em ObjC, em vez de se &quot;chamar&quot; métodos de objectos (como em Java ou C++), enviam-se &quot;mensagens&quot;  Sintaxe:       [receiver message ]          [receiver message: argument]       [receiver message: arg1 andArg: arg2]      Exemplos:      Veiculo *meuVeiculo; //assume this exists... [meuVeiculo trava]; [meuVeiculo setVelMax:300] //you wish!! ;-) [meuVeiculo vira:90 andPiscaPisca:YES]; int speed = [meuVeiculo velActual];
  • 11.
    ObjC: Mensagens paraObjectos O  &quot;Dot-Syntax &quot; O ObjC 2.0 introduziu uma outra forma de se aceder a variáveis membras de um objecto O dot-syntax faz uso dos setters e getters!! Não quebra o ENCAPSULAMENTO!! Veiculo *meuVeiculo; //assume this exists... int speed1 = [meuVeiculo velActual]; //message int speed2 = meuVeiculo . velActual; //dot syntax [meuVeiculo setVelActual: 120]; //message meuVeiculo.velActual = 60; //dot syntax
  • 12.
    ObjC: Mensagens paraObjectos O  &quot;Dot-Syntax &quot; - Um problema frequente... O que é que acontece quando o seguinte código executa? @implementation Person           - (void)setAge:(int)newAge { //setter              self.age = newAge; //age é uma variável membra          }          @end É equivalente a:          @implementation Person           - (void)setAge:(int)newAge { //setter              [self setAge:newAge] ; // Infinite loop!           }          @end
  • 13.
    ObjC: self e super self - mensagens para o próprio Objecto super  - mensagens para o &quot;pai&quot; do Objecto #import &quot;Veiculo.h&quot; @implementation Veiculo -(BOOL) isFamilyVehicle {      return ([self numLugares] >= 4); } //other method implementations... -(void) doSomething {      //call superclass implementation first...      [super doSomething];           //now do our own stuff...      int foo = bar;      //...  }
  • 14.
    ObjC: tipos dinâmicose est´ticos Objectos com tipos dinâmicos id anObject;  apenas id e não id* a não ser que se saiba o que se está a fazer... tipo genérico : pode ser usado para apontar para qualquer objecto Objectos com tipos estáticos Veiculo *meuVeiculo; O ObjC implementa verificação de tipos em compile-time (e não em run-time ) O ObjC usa sempre &quot;dynamic binding&quot;  
  • 15.
    ObjC: ciclo devida de objectos Criação de Objectos   Processo de dois passos:   alocar memória para o objecto: +alloc   inicializar o estado do objecto: -init Construtor Veiculo *meuVeiculo = nil; meuVeiculo = [[Veiculo alloc] init] ; #import &quot;Veiculo.h&quot;  @implementation Veiculo  - (id)init {       // allow superclass to initialize its state first       if ( self = [ super init ]) {          velMax = 120;          velActual = 0;          numRodas = 4;          numLugares = 4;      }       return self ; }  @end
  • 16.
    ObjC: ciclo devida de objectos Criação de Objectos - Métodos init (construtores)   Uma classe pode definir múltiplos métods init -(id) init;  -(id) initWithVelMax:(int) vel;  -(id) initWithVelMax:(int) vel velActual:(int) vel; ... Métodos menos específicos chamam tipicamente métodos mais específicos usando valores por omissão: -(id) init {return [self initWithVelMax: 120] ;} -(id) initWithVelMax :(int) vel {      return [self initWithVelMax:vel velActual:0] ; }
  • 17.
    ObjC: ciclo devida de objectos Destruição de Objectos   Depois de criado com com alloc (normalmente seguido de init ), e no caso de não mais ser necessário, um objecto deve ser &quot;limpo&quot; da memória!   Para cada alloc deverá haver um dealloc   caso contrário criam-se &quot; fugas de memória &quot;!! No entanto, d ealloc nunca é chamado directamente !   com uma excepção (ver mais à frente...)   existe um mecanismo para &quot;desalocar&quot; sem chamar dealloc  ...   REFERENCE COUNTING
  • 18.
    ObjC: ciclo devida de objectos Destruição de Objectos   REFERENCE COUNTING Todos os objectos implementam um &quot;retain count&quot; Herdado de NSObject enquanto o &quot;retain count&quot; > 0, objectivo é mantido em memória e válido +alloc e -copy criam objectos com &quot;retain count&quot; == 1 -retain incrementa o &quot;retain count&quot; -release decrementa o &quot;retain count&quot; Quando o &quot;retain count&quot; atinge o valor 0 o objecto é destruído! -dealloc é chamado automaticamente Ponto de não retorno!
  • 19.
    ObjC: ciclo devida de objectos Destruição de Objectos  -  REFERENCE COUNTING http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  • 20.
    ObjC: ciclo devida de objectos Destruição de Objectos   Veiculo *meuVeiculo = nil; meuVeiculo = [[Veiculo alloc] init]; [meuVeiculo setVelMax:120]; [meuVeiculo arranca]; [meuVeículo setVelActual: 50]; //... [meuVeiculo para];  //no more need for this object... [meuVeiculo release]; //meuVeiculo will be destroyed in case its retain //count is zero (i.e. no one else is pointing to it) //And in that case, sending messages to it will CRASH! [meuVeiculo arranca];//CRASH!!
  • 21.
    ObjC: ciclo devida de objectos Destruição de Objectos   Veiculo *meuVeiculo = nil; meuVeiculo = [[Veiculo alloc] init]; [meuVeiculo setVelMax:120]; [meuVeiculo arranca]; [meuVeículo setVelActual: 50]; //... [meuVeiculo para];  //no more need for this object... [meuVeiculo release]; meuVeiculo = nil; //good programming practice! [meuVeiculo arranca];//No longer crashes!:-) No effect...
  • 22.
    ObjC: ciclo devida de objectos Destruição de Objectos - Destrutor Implementação do método -dealloc   #import &quot;Veiculo.h&quot; @implementation Veiculo -dealloc { //this is an override of NSObject dealloc      //do any cleanup that is necessary...      //...      //when done, ask super to also clean itself up      [super dealloc]; //only time you call dealloc explicitly! } //other method implementations... @end
  • 23.
    ObjC: a classe NSString  Suporte genérico para strings Unicode Unicode é um sistema de codificação de caracteres que suporta todas as linguagens do mundo Consistentemente usada na API Cocoa e Cocoa Touch em prejuízo das C-strings (i.e. char * ) sem dúvida uma das classes mais usadas em Cocoa Em ObjC, &quot;constant strings&quot; são definidas como:      @“just as simple” E &quot;constant strings&quot; são na realidade instâncias de NSString                              NSString *aString = @”Hello World!”;
  • 24.
    ObjC: a classe NSString Formatação de Strings Semelhante ao usado em Java e C++ (e.g. printf ) %d - para int s %f  - para float s %c - para char s etc... %@ - para objectos!! --> ObjC          NSString *aString = @”Johnny”;          NSString *log = [NSString stringWithFormat: @”It’s ‘%@’”, aString];          //log would have been set to: &quot;It’s ‘Johnny’&quot;           NSLog(@”I am a %@, I have %d items”, [array className], [array count]);         //Would print: &quot;I am a NSArray, I have 5 items&quot;
  • 25.
    ObjC: apontadores nulos- nil Apontadores em ObjC podem ser nulos:          int *numberPtr = nil; Testando um apontador nulo, explicitamente:          if (numberPtr == nil) {return;} Testando um apontador nulo, implicitamente:          if (!numberPtr) {return;} Podem ser usados em atribuições ou argumentos:          numberPtr = nil;          [myCalculator setValue: nil]; Pode-se enviar mensagens para nil  (são ignoradas...):          myObject = nil;          [myObject doSomething];
  • 26.
    ObjC:  Identidade versusIgualdade entre Objectos Identidade Teste da igualdade dos respectivos apontadores &quot;É o mesmo Objecto?&quot;      if ( object1 == object2 ) {NSLog(@&quot;Same exact object instance&quot;);} Igualdade Teste da igualdade dos atributos (i.e. variáveis membras de cada objecto) &quot;Os Objectos têm o mesmo conteudo?&quot;       if ( [object1 isEqual: object2] ) {          NSLog(@&quot;Logically equivalent,                   but may be different object instances&quot;);      }
  • 27.
    ObjC: reponsabilidade pelavida de Objectos #import <Foundation/Foundation.h>  @interface Veiculo : NSObject {      // instance variables       NSString *marca; //Veiculo class “owns” the NSString object 'marca'        int velMax;      //...  }  // method declarations - (void)init;  - (NSString *)marca;  - (void)setMarca:(NSString *)novaMarca;  - (int)velMax; - (void)setVelMax:(int)vel; //...  @end
  • 28.
    ObjC: reponsabilidade pelavida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  - (id)init {       // allow superclass to initialize its state first       if (self = [super init]) {          marca = @&quot;não definida&quot;; //this is a NSString          velMax = 120;          velActual = 0;          numRodas = 4;          numLugares = 4;      }       return self; } //other method implementations...   @end
  • 29.
    ObjC: reponsabilidade pelavida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  - (NSString *)marca { return marca;}  - (void)setMarca:(NSString *)novaMarca {       marca = novaMarca; //!!! memory leak!! }  @end Se marca apontasse para uma NSString já existente (e.g. alocada no construtor init da classe Veiculo) essa zona de memória ficaria &quot;em fuga&quot;... Setter para um objecto criado pelo nosso objecto Solução 1 (errada)
  • 30.
    ObjC: reponsabilidade pelavida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  - (NSString *)marca { return marca;}  - (void)setMarca:(NSString *)novaMarca {       [marca release]; //what if marca == novaMarca?!?      marca = novaMarca; }  @end Se por acaso novaMarca apontasse para a mesma NSString que marca aponta (pode acontecer!!), ao fazer release do apontador marca correria-se o risco de o retain counter cair para zero, e a NSString ser destruida!! perder-se-ia a string que se pretendia usar para passar para o nosso objecto!! Setter para um objecto criado pelo nosso objecto Solução 2 (ainda errada)
  • 31.
    ObjC: reponsabilidade pelavida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  - (NSString *)marca { return marca;}  - (void)setMarca:(NSString *)novaMarca {      if ( marca != novaMarca )       {           [marca release];          marca = [novaMarca retain];           // marca’s retain count has been bumped up by 1      } }  @end Antes de tudo verifica-se se por acaso não estamos a receber um apontador para um objecto NSString para o qual já estamos a apontar Caso não seja, liberta-se o objecto anterior e aponta-se para o que é passado como argumento Setter para um objecto criado pelo nosso objecto Solução 3a (CORRECTA!)
  • 32.
    ObjC: reponsabilidade pelavida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  - (NSString *)marca { return marca;}  - (void)setMarca:(NSString *)novaMarca {      if ( marca != novaMarca )       {           [marca release];          marca = [novaMarca copy];           // marca’s retain count has been bumped up by 1      } }  @end Neste caso não copiamos apenas o apontador... É criada uma cópia do objecto!! Evita que alterações na string por alguém que partilhe apontadores para a &quot;nossa&quot; NSString marca Na realidade, como o objecto NSString é imutável , esse problema não se coloca...  Setter para um objecto criado pelo nosso objecto Solução 3b (CORRECTA!)
  • 33.
    ObjC: reponsabilidade pelavida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  //... -(void) dealloc {      //do any clean up that is needed...          [marca release];      //ask super to do its own clean up      [super dealloc];  }  @end Se alocamos... temos de &quot;desalocar&quot;!! Caso contrário provocamos uma &quot;fuga de memória&quot; (memory leak) Oh Yeah! Embrace the power!! ;-)
  • 34.
    ObjC: reponsabilidade pelavida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  //... -(NSString *) descricao  {       NSString *descricao ;      descricao = [ [NSString alloc] initWithFormat:@&quot;Veículo de %d rodas,                  com %d lugares...&quot;, [self numRodas], [self numLugares]);      //remember: [NSString alloc] above bumps the retain count (i.e. +1)!       return descricao ;     }  @end Retornar um objecto... ERRADO! fuga de memória! [NSString alloc] incrementa o retain count ... Mas em lado algum é feito o correspondente release !
  • 35.
    ObjC: reponsabilidade pelavida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  //... -(NSString *) descricao  {       NSString *descricao ;      descricao = [ [NSString alloc] initWithFormat:@&quot;Veículo de %d rodas,                  com %d lugares...&quot;, [self numRodas], [self numLugares]);      //remember: [NSString alloc] above bumps the retain count (i.e. +1)!      [descricao release]; //will this fix the memory leak? Yes... but we return bogus... :-\      return descricao ;     }  @end Retornar um objecto... ERRADO! Retorna um apontador para um objecto inválido! [NSString alloc] incrementa o retain count ... O  release  decrementa-o para zero dealloc é chamado... objecto é destruído Como resolver?!?!
  • 36.
    ObjC: reponsabilidade pelavida de Objectos #import &quot;Veiculo.h&quot;  @implementation Veiculo  //... -(NSString *) descricao  {       NSString *descricao ;      descricao = [ [NSString alloc] initWithFormat:@&quot;Veículo de %d rodas,                  com %d lugares...&quot;, [self numRodas], [self numLugares]);      //remember: [NSString alloc] above bumps the retain count (i.e. +1)!      [descricao autorelease]; //nice! ;-)      return descricao ;     }  @end Retornar um objecto... CORRECTO! É feito o release ao objecto, mas não imediatamente... Dá-se assim tempo ao código que chamou o método de receber o apontador para um objecto que (ainda é válido!) e de logo a seguir  fazer um retain   Quando é então feito o &quot;autorelease&quot;??!
  • 37.
    ObjC: reponsabilidade pelavida de Objectos O autorelease de Objectos chamando -autorelease &quot;marca&quot; um objecto para ser enviado um release num momento futuro...  Cumpre-se com o requisito de &quot;emparelhar&quot; cada alloc com um release Dando algum tempo ao objecto para sobreviver Forma conveniente de gerir memória muito útil em métodos que retornam objectos!
  • 38.
    ObjC: reponsabilidade pelavida de Objectos O autorelease e nomes de métodos Métodos cujos nomes comecem por alloc, copy ou new  devolvem (i.e. retornam) objectos com retain count == 1 É necessário fazer  release  quando o objecto não for mais necessário!!   Todos os outros métodos devolvem (i.e. retornam) objectos autoreleased (é apenas uma convenção!!) NSMutableString *string = [[NSMutableString alloc] init];  // We are responsible for calling -release or -autorelease  [string autorelease]; NSMutableString *string = [NSMutableString string];  // The method name doesn’t indicate that we need to release it  // So don’t- we’re cool!
  • 39.
    ObjC: reponsabilidade pelavida de Objectos Como funciona o  autorelease? Objectos são adicionados a um &quot;autorelease pool&quot; Este &quot;autorelease pool&quot; monitoriza objectos &quot;marcados&quot; para serem libertados (i.e. release d) Quando a própria &quot;autorelease pool&quot; é libertada, todos os objectos por ela monitorizados são também libertados (i.e. release d) Quando é a &quot;autorelease pool&quot; libertada??
  • 40.
    ObjC: reponsabilidade pelavida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  • 41.
    ObjC: reponsabilidade pelavida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  • 42.
    ObjC: reponsabilidade pelavida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  • 43.
    ObjC: reponsabilidade pelavida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  • 44.
    ObjC: reponsabilidade pelavida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  • 45.
    ObjC: reponsabilidade pelavida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  • 46.
    ObjC: reponsabilidade pelavida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  • 47.
    ObjC: reponsabilidade pelavida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  • 48.
    ObjC: reponsabilidade pelavida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  • 49.
    ObjC: reponsabilidade pelavida de Objectos Como funciona o  autorelease? http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  • 50.
    ObjC: reponsabilidade pelavida de Objectos E não se corre o risco de &quot;a qualquer momento&quot; um objecto criado com  autorelease  com ficar inválido e não poder usar um apontador para ele?? Nesse caso, há que fazer retain ! name = [NSMutableString string]; //autoreleased // We want to name to remain valid!  [name retain];  // ... // Eventually, we’ll release it (maybe in our -dealloc?)  [name release]; NOTA: autorelease não é Garbage Collection!! 
  • 51.
    Exercício: Classe Calculatore Fraction Implementar em ObjC uma classe Fraction: armazena fracções (i.e. numerador / denominador) imprime a fracção para a consola realiza operações (+, -, *, /) entre fracções #import <Foundation/Foundation.h> #import &quot;Fraction.h&quot; int main (int argc, const char * argv[]) {          NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Fraction *frac1 = [[Fraction alloc] init];          Fraction *frac2 = [[Fraction alloc] init]; [frac1 setTo: 1 over: 3]; [frac1 print]; //print to console something like &quot;1/3&quot;          [frac2 setTo: 5 over: 4];          Fraction* result = [frac1 add: frac2]; //adds two fractions          [result print]; [frac1 release];          [frac2 release];          [result release] [pool drain]; return 0; }
  • 52.
    Fim Cursos deVerão na Católica 2010 http://porto.ucp.pt/cvc/ Jorge C. S. Cardoso, Luís Gustavo Martins jorgecardoso@ieee.org, lmartins@porto.ucp.pt http://slideshare.net/jorgecardoso (tag: cvc2010) Código fonte:  http://db.tt/AOFOfA2