OOP ObjC

2,493 views

Published on

Slides do segundo dia do Workshop (intensivo :) ) sobre Introdução à Programação de Dispositivos Móveis (Google Android, Apple iPhone, iPod Touch e iPad)

Published in: Education
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,493
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
131
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

OOP ObjC

  1. 1. 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
  2. 2. Classe Veículo em ObjC <ul><li>Divisão do código em duas partes : </li></ul><ul><ul><ul><li>Interface </li></ul></ul></ul><ul><ul><ul><ul><li>declarada num ficheiro Veiculo.h </li></ul></ul></ul></ul><ul><ul><ul><li>Implementação </li></ul></ul></ul><ul><ul><ul><ul><li>definida num ficheiro Veiculo.m </li></ul></ul></ul></ul>http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  3. 3. 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
  4. 4. 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 <ul><ul><li>Implementar setters/getters </li></ul></ul><ul><ul><li>Implementar métodos </li></ul></ul><ul><li>Getters e setters podem ser criados automaticamente... </li></ul><ul><li>     - properties </li></ul><ul><li>     - synthesize </li></ul>
  5. 5. 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
  6. 6. 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
  7. 7. Classe Veículo em ObjC <ul><li>Uso de Properties e Synthesized Getters e Setters </li></ul><ul><ul><li>É possível alterar o comportamento do setter sintetizado para uma variável membra, usando modificadores </li></ul></ul>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. 8. Herança em ObjC <ul><ul><li>O ObjC suporta herança simples </li></ul></ul><ul><ul><ul><li>ou seja, uma classe apenas pode herdar de uma classe pai </li></ul></ul></ul><ul><ul><ul><ul><li>Tal como o Java (outras linguagens, como o C++, suportam herança múltipla) </li></ul></ul></ul></ul><ul><ul><ul><li>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) </li></ul></ul></ul><ul><ul><ul><ul><li>http://developer.apple.com/iphone/library/documentation/cocoa/conceptual/objectivec/Articles/ocCategories.html </li></ul></ul></ul></ul><ul><ul><ul><ul><li>http://developer.apple.com/iphone/library/documentation/cocoa/conceptual/objectivec/Articles/ocProtocols.html#//apple_ref/doc/uid/TP30001163-CH15-SW1 </li></ul></ul></ul></ul><ul><li>NSObject  • Root class  • Implements many basics  ■ Memory management  ■ Introspection  ■ Object equality </li></ul>http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  9. 9. ObjC: Métodos de Classe e de Instância <ul><ul><li>Instâncias respondem a métodos de instância: </li></ul></ul><ul><li>     - (id)   init; </li></ul><ul><li>     - (void) setVelMax: (int) vel;     </li></ul><ul><li>     - (int)  velMax; </li></ul><ul><li>     - (void) travar; </li></ul><ul><li>     ... </li></ul><ul><ul><li>Classes respondem a métodos de classe: </li></ul></ul><ul><li>     + (id) alloc; </li></ul><ul><li>     + (id) Veiculo; </li></ul><ul><li>     + (Veiculo *) sharedVeiculo; </li></ul><ul><li>     ... </li></ul>
  10. 10. ObjC: Mensagens para Objectos <ul><ul><li>Em ObjC, em vez de se &quot;chamar&quot; métodos de objectos (como em Java ou C++), enviam-se &quot;mensagens&quot;  </li></ul></ul><ul><ul><ul><li>Sintaxe:       [receiver message ]          [receiver message: argument]       [receiver message: arg1 andArg: arg2] </li></ul></ul></ul><ul><li>     </li></ul><ul><ul><li>Exemplos: </li></ul></ul><ul><li>     </li></ul>Veiculo *meuVeiculo; //assume this exists... [meuVeiculo trava]; [meuVeiculo setVelMax:300] //you wish!! ;-) [meuVeiculo vira:90 andPiscaPisca:YES]; int speed = [meuVeiculo velActual];
  11. 11. ObjC: Mensagens para Objectos <ul><ul><li>O  &quot;Dot-Syntax &quot; </li></ul></ul><ul><ul><ul><li>O ObjC 2.0 introduziu uma outra forma de se aceder a variáveis membras de um objecto </li></ul></ul></ul><ul><ul><ul><li>O dot-syntax faz uso dos setters e getters!! </li></ul></ul></ul><ul><ul><ul><ul><li>Não quebra o ENCAPSULAMENTO!! </li></ul></ul></ul></ul>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. 12. ObjC: Mensagens para Objectos <ul><ul><li>O  &quot;Dot-Syntax &quot; - Um problema frequente... </li></ul></ul><ul><ul><ul><li>O que é que acontece quando o seguinte código executa? @implementation Person  </li></ul></ul></ul><ul><li>         - (void)setAge:(int)newAge { //setter              self.age = newAge; //age é uma variável membra </li></ul><ul><li>         } </li></ul><ul><li>         @end </li></ul><ul><ul><ul><li>É equivalente a: </li></ul></ul></ul><ul><li>         @implementation Person </li></ul><ul><li>          - (void)setAge:(int)newAge { //setter              [self setAge:newAge] ; // Infinite loop!  </li></ul><ul><li>         } </li></ul><ul><li>         @end </li></ul>
  13. 13. ObjC: self e super <ul><ul><li>self - mensagens para o próprio Objecto </li></ul></ul><ul><ul><li>super  - mensagens para o &quot;pai&quot; do Objecto </li></ul></ul>#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. 14. ObjC: tipos dinâmicos e est´ticos <ul><ul><li>Objectos com tipos dinâmicos </li></ul></ul><ul><ul><ul><li>id anObject;  </li></ul></ul></ul><ul><ul><ul><ul><li>apenas id e não id* </li></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>a não ser que se saiba o que se está a fazer... </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><li>tipo genérico : pode ser usado para apontar para qualquer objecto </li></ul></ul></ul></ul><ul><ul><li>Objectos com tipos estáticos </li></ul></ul><ul><ul><ul><li>Veiculo *meuVeiculo; </li></ul></ul></ul><ul><ul><li>O ObjC implementa verificação de tipos em compile-time (e não em run-time ) </li></ul></ul><ul><ul><li>O ObjC usa sempre &quot;dynamic binding&quot;   </li></ul></ul>
  15. 15. ObjC: ciclo de vida de objectos <ul><ul><li>Criação de Objectos </li></ul></ul><ul><ul><ul><li>  Processo de dois passos: </li></ul></ul></ul><ul><ul><ul><ul><li>  alocar memória para o objecto: +alloc </li></ul></ul></ul></ul><ul><ul><ul><ul><li>  inicializar o estado do objecto: -init </li></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>Construtor </li></ul></ul></ul></ul></ul>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. 16. ObjC: ciclo de vida de objectos <ul><ul><li>Criação de Objectos - Métodos init (construtores) </li></ul></ul><ul><ul><ul><li>  Uma classe pode definir múltiplos métods init </li></ul></ul></ul><ul><ul><ul><ul><li>-(id) init;  </li></ul></ul></ul></ul><ul><ul><ul><ul><li>-(id) initWithVelMax:(int) vel;  </li></ul></ul></ul></ul><ul><ul><ul><ul><li>-(id) initWithVelMax:(int) vel velActual:(int) vel; </li></ul></ul></ul></ul><ul><ul><ul><ul><li>... </li></ul></ul></ul></ul><ul><ul><ul><li>Métodos menos específicos chamam tipicamente métodos mais específicos usando valores por omissão: </li></ul></ul></ul><ul><li>-(id) init {return [self initWithVelMax: 120] ;} </li></ul><ul><li>-(id) initWithVelMax :(int) vel { </li></ul><ul><li>     return [self initWithVelMax:vel velActual:0] ; </li></ul><ul><li>} </li></ul>
  17. 17. ObjC: ciclo de vida de objectos <ul><ul><li>Destruição de Objectos   </li></ul></ul><ul><ul><ul><li>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! </li></ul></ul></ul><ul><ul><ul><ul><li>  Para cada alloc deverá haver um dealloc </li></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>  caso contrário criam-se &quot; fugas de memória &quot;!! </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><li>No entanto, d ealloc nunca é chamado directamente ! </li></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>  com uma excepção (ver mais à frente...) </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>  existe um mecanismo para &quot;desalocar&quot; sem chamar dealloc  ... </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>  REFERENCE COUNTING </li></ul></ul></ul></ul></ul>
  18. 18. ObjC: ciclo de vida de objectos <ul><ul><li>Destruição de Objectos   </li></ul></ul><ul><ul><ul><li>REFERENCE COUNTING </li></ul></ul></ul><ul><ul><ul><ul><li>Todos os objectos implementam um &quot;retain count&quot; </li></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>Herdado de NSObject </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>enquanto o &quot;retain count&quot; > 0, objectivo é mantido em memória e válido </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><li>+alloc e -copy criam objectos com &quot;retain count&quot; == 1 </li></ul></ul></ul></ul><ul><ul><ul><ul><li>-retain incrementa o &quot;retain count&quot; </li></ul></ul></ul></ul><ul><ul><ul><ul><li>-release decrementa o &quot;retain count&quot; </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Quando o &quot;retain count&quot; atinge o valor 0 o objecto é destruído! </li></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>-dealloc é chamado automaticamente </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>Ponto de não retorno! </li></ul></ul></ul></ul></ul>
  19. 19. ObjC: ciclo de vida de objectos <ul><ul><li>Destruição de Objectos  -  REFERENCE COUNTING </li></ul></ul>http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  20. 20. ObjC: ciclo de vida de objectos <ul><ul><li>Destruição de Objectos   </li></ul></ul>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. 21. ObjC: ciclo de vida de objectos <ul><ul><li>Destruição de Objectos   </li></ul></ul>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. 22. ObjC: ciclo de vida de objectos <ul><ul><li>Destruição de Objectos - Destrutor </li></ul></ul><ul><ul><ul><li>Implementação do método -dealloc   </li></ul></ul></ul>#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. 23. ObjC: a classe NSString <ul><ul><li> Suporte genérico para strings Unicode </li></ul></ul><ul><ul><ul><li>Unicode é um sistema de codificação de caracteres que suporta todas as linguagens do mundo </li></ul></ul></ul><ul><ul><li>Consistentemente usada na API Cocoa e Cocoa Touch </li></ul></ul><ul><ul><ul><li>em prejuízo das C-strings (i.e. char * ) </li></ul></ul></ul><ul><ul><ul><li>sem dúvida uma das classes mais usadas em Cocoa </li></ul></ul></ul><ul><ul><li>Em ObjC, &quot;constant strings&quot; são definidas como: </li></ul></ul><ul><li>     @“just as simple” </li></ul><ul><ul><li>E &quot;constant strings&quot; são na realidade instâncias de NSString </li></ul></ul><ul><li>                             NSString *aString = @”Hello World!”; </li></ul>
  24. 24. ObjC: a classe NSString <ul><ul><li>Formatação de Strings </li></ul></ul><ul><ul><ul><li>Semelhante ao usado em Java e C++ (e.g. printf ) </li></ul></ul></ul><ul><ul><ul><ul><li>%d - para int s </li></ul></ul></ul></ul><ul><ul><ul><ul><li>%f  - para float s </li></ul></ul></ul></ul><ul><ul><ul><ul><li>%c - para char s </li></ul></ul></ul></ul><ul><ul><ul><ul><li>etc... </li></ul></ul></ul></ul><ul><ul><ul><ul><li>%@ - para objectos!! --> ObjC </li></ul></ul></ul></ul><ul><li>         NSString *aString = @”Johnny”; </li></ul><ul><li>         NSString *log = [NSString stringWithFormat: @”It’s ‘%@’”, aString]; </li></ul><ul><li>         //log would have been set to: &quot;It’s ‘Johnny’&quot;  </li></ul><ul><li>         NSLog(@”I am a %@, I have %d items”, [array className], [array count]); </li></ul><ul><li>        //Would print: &quot;I am a NSArray, I have 5 items&quot; </li></ul>
  25. 25. ObjC: apontadores nulos - nil <ul><ul><li>Apontadores em ObjC podem ser nulos: </li></ul></ul><ul><li>         int *numberPtr = nil; </li></ul><ul><ul><li>Testando um apontador nulo, explicitamente: </li></ul></ul><ul><li>         if (numberPtr == nil) {return;} </li></ul><ul><ul><li>Testando um apontador nulo, implicitamente: </li></ul></ul><ul><li>         if (!numberPtr) {return;} </li></ul><ul><ul><li>Podem ser usados em atribuições ou argumentos: </li></ul></ul><ul><li>         numberPtr = nil; </li></ul><ul><li>         [myCalculator setValue: nil]; </li></ul><ul><ul><li>Pode-se enviar mensagens para nil  (são ignoradas...): </li></ul></ul><ul><li>         myObject = nil; </li></ul><ul><li>         [myObject doSomething]; </li></ul>
  26. 26. ObjC:  Identidade versus Igualdade entre Objectos <ul><ul><li>Identidade </li></ul></ul><ul><ul><ul><li>Teste da igualdade dos respectivos apontadores </li></ul></ul></ul><ul><ul><ul><li>&quot;É o mesmo Objecto?&quot; </li></ul></ul></ul><ul><li>     if ( object1 == object2 ) {NSLog(@&quot;Same exact object instance&quot;);} </li></ul><ul><ul><li>Igualdade </li></ul></ul><ul><ul><ul><li>Teste da igualdade dos atributos (i.e. variáveis membras de cada objecto) </li></ul></ul></ul><ul><ul><ul><li>&quot;Os Objectos têm o mesmo conteudo?&quot;  </li></ul></ul></ul><ul><li>     if ( [object1 isEqual: object2] ) {          NSLog(@&quot;Logically equivalent,  </li></ul><ul><li>                 but may be different object instances&quot;); </li></ul><ul><li>     } </li></ul>
  27. 27. ObjC: reponsabilidade pela vida de Objectos <ul><li>#import <Foundation/Foundation.h>  @interface Veiculo : NSObject {      // instance variables  </li></ul><ul><li>     NSString *marca; //Veiculo class “owns” the NSString object 'marca'   </li></ul><ul><li>     int velMax; </li></ul><ul><li>     //...  }  // method declarations </li></ul><ul><li>- (void)init;  - (NSString *)marca;  </li></ul><ul><li>- (void)setMarca:(NSString *)novaMarca;  - (int)velMax; </li></ul><ul><li>- (void)setVelMax:(int)vel; </li></ul><ul><li>//...  @end </li></ul>
  28. 28. 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
  29. 29. ObjC: reponsabilidade pela vida de Objectos <ul><li>#import &quot;Veiculo.h&quot;  @implementation Veiculo  - (NSString *)marca { return marca;}  </li></ul><ul><li>- (void)setMarca:(NSString *)novaMarca {  </li></ul><ul><li>     marca = novaMarca; //!!! memory leak!! </li></ul><ul><li>}  </li></ul><ul><li>@end </li></ul><ul><ul><li>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;... </li></ul></ul>Setter para um objecto criado pelo nosso objecto Solução 1 (errada)
  30. 30. ObjC: reponsabilidade pela vida de Objectos <ul><li>#import &quot;Veiculo.h&quot;  @implementation Veiculo  - (NSString *)marca { return marca;}  </li></ul><ul><li>- (void)setMarca:(NSString *)novaMarca {  </li></ul><ul><li>     [marca release]; //what if marca == novaMarca?!? </li></ul><ul><li>     marca = novaMarca; </li></ul><ul><li>}  </li></ul><ul><li>@end </li></ul><ul><ul><li>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!! </li></ul></ul><ul><ul><ul><li>perder-se-ia a string que se pretendia usar para passar para o nosso objecto!! </li></ul></ul></ul>Setter para um objecto criado pelo nosso objecto Solução 2 (ainda errada)
  31. 31. ObjC: reponsabilidade pela vida de Objectos <ul><li>#import &quot;Veiculo.h&quot;  @implementation Veiculo  - (NSString *)marca { return marca;}  </li></ul><ul><li>- (void)setMarca:(NSString *)novaMarca {      if ( marca != novaMarca )  </li></ul><ul><li>     {  </li></ul><ul><li>         [marca release];          marca = [novaMarca retain];  </li></ul><ul><li>         // marca’s retain count has been bumped up by 1 </li></ul><ul><li>     } }  </li></ul><ul><li>@end </li></ul><ul><ul><li>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 </li></ul></ul><ul><ul><ul><li>Caso não seja, liberta-se o objecto anterior e aponta-se para o que é passado como argumento </li></ul></ul></ul>Setter para um objecto criado pelo nosso objecto Solução 3a (CORRECTA!)
  32. 32. ObjC: reponsabilidade pela vida de Objectos <ul><li>#import &quot;Veiculo.h&quot;  @implementation Veiculo  - (NSString *)marca { return marca;}  </li></ul><ul><li>- (void)setMarca:(NSString *)novaMarca {      if ( marca != novaMarca )  </li></ul><ul><li>     {  </li></ul><ul><li>         [marca release];          marca = [novaMarca copy];  </li></ul><ul><li>         // marca’s retain count has been bumped up by 1 </li></ul><ul><li>     } }  </li></ul><ul><li>@end </li></ul><ul><ul><li>Neste caso não copiamos apenas o apontador... </li></ul></ul><ul><ul><ul><li>É criada uma cópia do objecto!! </li></ul></ul></ul><ul><ul><ul><ul><li>Evita que alterações na string por alguém que partilhe apontadores para a &quot;nossa&quot; NSString marca </li></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>Na realidade, como o objecto NSString é imutável , esse problema não se coloca...  </li></ul></ul></ul></ul></ul>Setter para um objecto criado pelo nosso objecto Solução 3b (CORRECTA!)
  33. 33. ObjC: reponsabilidade pela vida de Objectos <ul><li>#import &quot;Veiculo.h&quot;  @implementation Veiculo  </li></ul><ul><li>//... </li></ul><ul><li>-(void) dealloc { </li></ul><ul><li>     //do any clean up that is needed...     </li></ul><ul><li>     [marca release]; </li></ul><ul><li>     //ask super to do its own clean up </li></ul><ul><li>     [super dealloc];  </li></ul><ul><li>}  </li></ul><ul><li>@end </li></ul><ul><ul><li>Se alocamos... temos de &quot;desalocar&quot;!! </li></ul></ul><ul><ul><ul><li>Caso contrário provocamos uma &quot;fuga de memória&quot; (memory leak) </li></ul></ul></ul>Oh Yeah! Embrace the power!! ;-)
  34. 34. ObjC: reponsabilidade pela vida de Objectos <ul><li>#import &quot;Veiculo.h&quot;  @implementation Veiculo  </li></ul><ul><li>//... </li></ul><ul><li>-(NSString *) descricao  {  </li></ul><ul><li>     NSString *descricao ; </li></ul><ul><li>     descricao = [ [NSString alloc] initWithFormat:@&quot;Veículo de %d rodas, </li></ul><ul><li>                 com %d lugares...&quot;, [self numRodas], [self numLugares]); </li></ul><ul><li>     //remember: [NSString alloc] above bumps the retain count (i.e. +1)!  </li></ul><ul><li>     return descricao ;     </li></ul><ul><li>}  </li></ul><ul><li>@end </li></ul><ul><ul><li>Retornar um objecto... </li></ul></ul><ul><ul><li>ERRADO! fuga de memória! </li></ul></ul><ul><ul><ul><li>[NSString alloc] incrementa o retain count ... </li></ul></ul></ul><ul><ul><ul><li>Mas em lado algum é feito o correspondente release ! </li></ul></ul></ul>
  35. 35. ObjC: reponsabilidade pela vida de Objectos <ul><li>#import &quot;Veiculo.h&quot;  @implementation Veiculo  </li></ul><ul><li>//... </li></ul><ul><li>-(NSString *) descricao  {  </li></ul><ul><li>     NSString *descricao ; </li></ul><ul><li>     descricao = [ [NSString alloc] initWithFormat:@&quot;Veículo de %d rodas, </li></ul><ul><li>                 com %d lugares...&quot;, [self numRodas], [self numLugares]); </li></ul><ul><li>     //remember: [NSString alloc] above bumps the retain count (i.e. +1)! </li></ul><ul><li>     [descricao release]; //will this fix the memory leak? Yes... but we return bogus... :- </li></ul><ul><li>     return descricao ;     </li></ul><ul><li>}  </li></ul><ul><li>@end </li></ul><ul><ul><li>Retornar um objecto... </li></ul></ul><ul><ul><li>ERRADO! Retorna um apontador para um objecto inválido! </li></ul></ul><ul><ul><ul><li>[NSString alloc] incrementa o retain count ... </li></ul></ul></ul><ul><ul><ul><li>O  release  decrementa-o para zero </li></ul></ul></ul><ul><ul><ul><ul><li>dealloc é chamado... objecto é destruído </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Como resolver?!?! </li></ul></ul></ul></ul>
  36. 36. ObjC: reponsabilidade pela vida de Objectos <ul><li>#import &quot;Veiculo.h&quot;  @implementation Veiculo  </li></ul><ul><li>//... </li></ul><ul><li>-(NSString *) descricao  {  </li></ul><ul><li>     NSString *descricao ; </li></ul><ul><li>     descricao = [ [NSString alloc] initWithFormat:@&quot;Veículo de %d rodas, </li></ul><ul><li>                 com %d lugares...&quot;, [self numRodas], [self numLugares]); </li></ul><ul><li>     //remember: [NSString alloc] above bumps the retain count (i.e. +1)! </li></ul><ul><li>     [descricao autorelease]; //nice! ;-) </li></ul><ul><li>     return descricao ;     </li></ul><ul><li>}  </li></ul><ul><li>@end </li></ul><ul><ul><li>Retornar um objecto... </li></ul></ul><ul><ul><li>CORRECTO! </li></ul></ul><ul><ul><ul><li>É feito o release ao objecto, mas não imediatamente... </li></ul></ul></ul><ul><ul><ul><ul><li>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 </li></ul></ul></ul></ul><ul><ul><ul><li>  Quando é então feito o &quot;autorelease&quot;??! </li></ul></ul></ul>
  37. 37. ObjC: reponsabilidade pela vida de Objectos <ul><ul><li>O autorelease de Objectos </li></ul></ul><ul><ul><ul><li>chamando -autorelease &quot;marca&quot; um objecto para ser enviado um release num momento futuro...  </li></ul></ul></ul><ul><ul><ul><li>Cumpre-se com o requisito de &quot;emparelhar&quot; cada alloc com um release </li></ul></ul></ul><ul><ul><ul><ul><li>Dando algum tempo ao objecto para sobreviver </li></ul></ul></ul></ul><ul><ul><ul><li>Forma conveniente de gerir memória </li></ul></ul></ul><ul><ul><ul><ul><li>muito útil em métodos que retornam objectos! </li></ul></ul></ul></ul>
  38. 38. ObjC: reponsabilidade pela vida de Objectos <ul><ul><li>O autorelease e nomes de métodos </li></ul></ul><ul><ul><ul><li>Métodos cujos nomes comecem por alloc, copy ou new  devolvem (i.e. retornam) objectos com retain count == 1 </li></ul></ul></ul><ul><ul><ul><ul><li>É necessário fazer  release  quando o objecto não for mais necessário!!   </li></ul></ul></ul></ul><ul><ul><ul><li>Todos os outros métodos devolvem (i.e. retornam) objectos autoreleased (é apenas uma convenção!!) </li></ul></ul></ul>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. 39. ObjC: reponsabilidade pela vida de Objectos <ul><ul><li>Como funciona o  autorelease? </li></ul></ul><ul><ul><ul><li>Objectos são adicionados a um &quot;autorelease pool&quot; </li></ul></ul></ul><ul><ul><ul><li>Este &quot;autorelease pool&quot; monitoriza objectos &quot;marcados&quot; para serem libertados (i.e. release d) </li></ul></ul></ul><ul><ul><ul><ul><li>Quando a própria &quot;autorelease pool&quot; é libertada, todos os objectos por ela monitorizados são também libertados (i.e. release d) </li></ul></ul></ul></ul><ul><ul><ul><li>Quando é a &quot;autorelease pool&quot; libertada?? </li></ul></ul></ul>
  40. 40. ObjC: reponsabilidade pela vida de Objectos <ul><ul><li>Como funciona o  autorelease? </li></ul></ul>http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  41. 41. ObjC: reponsabilidade pela vida de Objectos <ul><ul><li>Como funciona o  autorelease? </li></ul></ul>http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  42. 42. ObjC: reponsabilidade pela vida de Objectos <ul><ul><li>Como funciona o  autorelease? </li></ul></ul>http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  43. 43. ObjC: reponsabilidade pela vida de Objectos <ul><ul><li>Como funciona o  autorelease? </li></ul></ul>http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  44. 44. ObjC: reponsabilidade pela vida de Objectos <ul><ul><li>Como funciona o  autorelease? </li></ul></ul>http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  45. 45. ObjC: reponsabilidade pela vida de Objectos <ul><ul><li>Como funciona o  autorelease? </li></ul></ul>http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  46. 46. ObjC: reponsabilidade pela vida de Objectos <ul><ul><li>Como funciona o  autorelease? </li></ul></ul>http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  47. 47. ObjC: reponsabilidade pela vida de Objectos <ul><ul><li>Como funciona o  autorelease? </li></ul></ul>http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  48. 48. ObjC: reponsabilidade pela vida de Objectos <ul><ul><li>Como funciona o  autorelease? </li></ul></ul>http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  49. 49. ObjC: reponsabilidade pela vida de Objectos <ul><ul><li>Como funciona o  autorelease? </li></ul></ul>http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-winter
  50. 50. ObjC: reponsabilidade pela vida de Objectos <ul><ul><li>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?? </li></ul></ul><ul><ul><ul><li>Nesse caso, há que fazer retain ! </li></ul></ul></ul>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. 51. Exercício: Classe Calculator e Fraction <ul><ul><li>Implementar em ObjC uma classe Fraction: </li></ul></ul><ul><ul><ul><li>armazena fracções (i.e. numerador / denominador) </li></ul></ul></ul><ul><ul><ul><li>imprime a fracção para a consola </li></ul></ul></ul><ul><ul><ul><li>realiza operações (+, -, *, /) entre fracções </li></ul></ul></ul>#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. 52. Fim <ul><li>Cursos de Verão na Católica 2010 </li></ul><ul><li>http://porto.ucp.pt/cvc/ </li></ul>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

×