Pergunta

Eu estou usando um quadro que define e usos 'ClassA', uma subclasse de NSObject. Eu gostaria de adicionar algumas variáveis ??e funcionalidade tão naturalmente que eu criei 'ClassB', uma subclasse de 'ClassA'

Agora o meu problema é este. Muitos dos métodos dentro desta casos de retorno quadro de 'ClassA', que eu gostaria de elenco para meu subclasse.

Por exemplo tomar este método:

- (ClassA *)doSomethingCool:(int)howCool

Agora, no meu código que eu tente o seguinte:

ClassB * objB;
objB = (ClassB *)doSomethingCool(10); 

NSLog(@"objB className = %@", [objB className]);

Isto funciona muito bem. Sem compilação ou erros de execução ou qualquer coisa. Mas o que é realmente estranho para mim é a saída:

>> "objB className = ClassA"

O elenco obviamente falhou. Não tenho certeza o que aconteceu a este ponto ... objB é digitado como 'ClassB', mas é className é 'ClassA' e não irá responder a métodos de qualquer tipo de 'ClassB'.

Não tenho certeza como isso é possível ... Alguém sabe o que estou fazendo de errado aqui?

Eu encontrei um post semelhante que é exatamente o oposto do que eu estou pedindo aqui

Foi útil?

Solução

Fundição variáveis ??de objeto no Objective-C é geralmente um erro (existem alguns casos onde é certo, mas nunca para esse tipo de coisa). Observe que você não está lançando um objeto - você está lançando um ponteiro para um objeto. Então você tem um ponteiro do tipo ClassB*, mas ainda aponta para a mesma instância do ClassA. A coisa apontou para não mudou em nada.

Se você realmente deseja converter instâncias de ClassA para ClassB, você precisa escrever um método construtor ClassB que pode criar uma instância de ClassB de um ClassA. Se você realmente precisa adicionar variáveis ??de instância, esta pode ser sua melhor escolha.

Como Jason disse, no entanto, é muitas vezes uma boa idéia para tentar uma categoria pela primeira vez.

Outras dicas

Você não pode simplesmente lançar uma super classe para sua subclasse. Na verdade, não implementar qualquer um dos seus variáveis ??/ propriedades ou métodos adicionais. Assim que você tentar mensagem com um método que você definir na sua subclasse, você está indo para obter uma exceção de tempo de execução e sua aplicação vai sair. Você só pode lançar com segurança em uma direção: do mais específico para mais geral. Ou seja, você pode lançar o nosso ClassB a um ClassA com segurança, usando apenas os métodos e propriedades de ClassA, mas não o contrário.

Pense nisso desta maneira: você tem um carro (classe pai) e um FourDoorSedan (a subclasse). Cada carro tem um motor e duas portas. Agora, digamos que você está recebendo um carro de algum lugar, e isso é realmente tudo o que você sabe sobre ele. Você diz ao operador, esse carro é um FourDoorSedan, mas na verdade ele sair não é. Então, quando o operador faz algo como: openBackPassengerDoor, o que acontece? Existem apenas duas portas !! É o mesmo aqui.

Se você quiser apenas adicionar um pouco de funcionalidade para ClassA, veja a Objective-C Categorias, eles são provavelmente o que você quer e será exigido nenhum casting. Leia a documentação com cuidado, no entanto, porque eles não são sem suas advertências.

Se você quiser apenas adicionar um método para objetos existentes, subclasses não é a maneira correta. Você pode adicionar método para classes existentes (e suas instâncias) usando um recurso de linguagem chamada categoria .

Exemplo:

//"ClassA+doSomethingCool.h"
@interface ClassA (doSomethingCool)
- (ClassA *)doSomethingCool:(int)howCool;
@end


//"ClassA+doSomethingCool.m"
@implementation ClassA (doSomethingCool)
- (ClassA *)doSomethingCool:(int)howCool
{

}
@end

Fundição não converter de um tipo de objeto para outro. Você não pode forçar alguma biblioteca com o tipo de mudança de objeto e criar um outro tipo de objetos a menos que ele utiliza algum padrão de fábrica.

O que acontece quando você chamar um de seus métodos de subclasse do objeto retornado?

ClassB * objB;
objB = (ClassB *)doSomethingCool(10);
[objB subClassMethod];

Obj-C é bastante livre e perder com os tipos, você não precisa mesmo de saber o tipo antes de mão, por exemplo. você poderia mudar todas as suas referências ClassB para id. Eu sei que é mais seguro saber que você tem o tipo esperado, mas se o seu código está correto não deveria importar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top