Inferência do tipo Objective-C.
-
21-09-2019 - |
Pergunta
Ok, tenho a sensação de que vocês serão capazes de apontar rapidamente por que estou tão confuso sobre isso, mas tenho uma pergunta sobre por que o seguinte não resulta em um erro do compilador ou aviso:
NSString * intValue = [ NSString stringWithFormat:@"int = %i", [ [ self.selectedObject valueForKey:name ] integerValue ] ];
selectedObject
é um NSObject
, e name
acontece que é o nome de um @property
do tipo int
.
O que me perplexos é por que o compilador está perfeitamente disposto a assumir que o resultado de retorno de [ self.selectedObject valueForKey:name ]
é do tipo NSNumber *
(sem digitá -lo) para encadear a mensagem com uma chamada para integerValue
.
Obviamente, o KVC encerra tipos de "número" de objeto em NSNumber
, mas não há como o compilador saber que -valueForKey:
Vai devolver um NSNumber *
neste caso em particular.
Por que isso não resulta em um aviso de compilador ao longo das linhas de "id
pode não responder a '-integerValue
'"?
Solução
Espero ter acertado: isso é porque id
é "especial". Objetos do id
O tipo pode receber qualquer mensagem que você desejar, não há verificação feita pelo compilador e tudo será verificado no tempo de execução. Ou, em outras palavras, o id
Tipo é a parte "dinâmica de digitação" do Objective-C, enquanto todos os outros tipos (como NSObject
) são a parte da "digitação estática".
Dessa forma, você pode escolher onde deseja usar digitação estática e onde deseja usar a digitação dinâmica. É perfeitamente legal fazer algo assim:
id str1 = @"Hello";
id str2 = [str1 stringByAppendingString:@", world"];
Mas geralmente você digita as cordas "firmemente" como NSString
s, porque você obtém a conveniência da verificação do tipo estático no tempo de compilação e só recorda a uma digitação dinâmica onde o estático atrapalharia, como no valueForKey
situação.
Outras dicas
O tempo é passado e temos melhor inferência de tipo agora graças ao __auto_type
Disponível desde o Xcode 8. Então agora você pode fazer
#define let __auto_type const
#define var __auto_type
let a = @[@"pew pew"];
var b = 2;
b = a; //compiler warning "Incompatible pointer to integer conversion assigning to 'int' from 'NSArray *__strong const'"
Na verdade, eu gostei tanto disso, então fiz isso como um pod por conveniência.
pod 'SwiftyObjC'