Em Swift, alguém pode explicar como substituir uma propriedade em uma superclasse por outro objeto subclassificado da propriedade original?
Veja este exemplo simples:
class Chassis {}
class RacingChassis : Chassis {}
class Car {
let chassis = Chassis()
}
class RaceCar: Car {
override let chassis = RacingChassis() //Error here
}
Isso dá o erro:
Cannot override with a stored property 'chassis'
Se eu tiver chassi como 'var', recebo o erro:
Cannot override mutable property 'chassis' of type 'Chassis' with covariant type 'RacingChassis'
A única coisa que encontrei no guia em "Substituindo propriedades" indica que precisamos substituir o getter e o setter, o que pode funcionar para alterar o valor da propriedade (se for 'var'), mas e quanto à alteração da classe de propriedade ?
strong
propriedade e estava recebendo um erro ao tentar substituí-la - mas parece que perdi que isso se traduz em um "opcional implicitamente desembrulhado" (chassis!
) em Swift, entãooverride var chassis : Chassis!
conserta.Isso parece funcionar
fonte
let
naCar
classe que impossibilita a alteração. Só podemos alterar achassis
propriedade naRaceCar
classe.Tente o seguinte:
Então:
Detalhe em http://www.mylonly.com/14957025459875.html
fonte
O Solution Dash fornecido funciona bem, exceto que a superclasse deve ser declarada com a palavra-chave let em vez de var. Aqui está uma solução que é possível, mas NÃO RECOMENDADA!
A solução abaixo será compilada com o Xcode 6.2, SWIFT 1.1 (se todas as classes estiverem em arquivos swift diferentes), mas deve ser evitada porque PODE LEVAR A COMPORTAMENTOS INESPERADOS (INCLUINDO UM CRASH, especialmente ao usar tipos não opcionais). NOTA: ISSO NÃO FUNCIONA COM O XCODE 6.3 BETA 3, SWIFT 1.2
fonte
Teoricamente, você pode fazê-lo desta maneira ...
Isso funciona perfeitamente em um playground do Xcode.
Mas , se você tentar fazer isso em um projeto real, um erro do compilador informará:
Eu só verifiquei o Xcode 6.0 GM a partir de agora.
Infelizmente, você terá que esperar até que a Apple resolva isso.
Também enviei um relatório de erro. 18518795
fonte
Eu já vi várias razões pelas quais projetar uma API usando variáveis em vez de funções é problemático e, para mim, usar propriedades computadas parece uma solução alternativa. Existem boas razões para manter suas variáveis de instância encapsuladas. Aqui eu criei um protocolo Automóvel com o qual o carro está em conformidade. Este protocolo possui um método acessador que retorna um objeto Chassis. Como o carro está em conformidade, a subclasse RaceCar pode substituí-lo e retornar uma subclasse Chassis diferente. Isso permite que a classe Car programe para uma interface (Automóvel) e a classe RaceCar que conhece o RacingChassis pode acessar diretamente a variável _racingChassis.
Outro exemplo de por que o design de uma API usando variáveis é interrompido é quando você tem variáveis em um protocolo. Se você quiser dividir todas as funções de protocolo em extensões, você pode, exceto que as propriedades armazenadas não podem ser colocadas em extensões e precisam ser definidas na classe (para compilar isso, você precisa descomentar o código em Classe AdaptableViewController e remova a variável mode da extensão):
O código acima terá este erro do compilador: "As extensões podem não ter propriedades armazenadas". Aqui está como você pode reescrever o exemplo acima, para que tudo no protocolo possa ser separado na extensão usando as funções:
fonte
Você pode conseguir isso com o uso de genéricos:
Com essa abordagem, você terá 100% de código de segurança, sem forçar a abertura.
Mas isso é meio que um hack e, se você precisar redefinir várias propriedades, as declarações de classe parecerão uma bagunça total. Portanto, tenha cuidado com essa abordagem.
fonte
Dependendo de como você planeja usar a propriedade, a maneira mais simples de fazer isso é usar um tipo opcional para sua subclasse e substituir o
didSet {}
método para a super:Obviamente, você precisa gastar algum tempo verificando para garantir que as classes possam ser inicializadas dessa maneira, mas, configurando as propriedades como opcional, você se protege contra situações nas quais a transmissão não funciona mais.
fonte
Você pode simplesmente criar outra variável do RacingChassis.
fonte
chassis
e permitindo que obtenhamos / configuremos nossaRacingChassis
instância com achassis
propriedadeTente o seguinte:
fonte
fonte
A seguir, é possível usar um único objeto nas classes base e derivada. Na classe derivada, use a propriedade do objeto derivado.
fonte
Uma ligeira variação de outras respostas, mas mais simples e segura, com alguns benefícios interessantes.
Os benefícios incluem que não há restrição sobre o que o chassi deve ser (var, let, opcional etc.), e é fácil subclassificar o RaceCar. As subclasses do RaceCar podem ter seu próprio valor calculado para o chassi (ou racingChassis).
fonte
basta definir uma nova propriedade imageview com uma convenção de nomenclatura diferente, como imgview, porque o imageView já é de sua propriedade e não podemos atribuir duas propriedades fortes.
fonte