Normalmente, o downcasting é o que você faz quando o conhecimento estaticamente conhecido que o compilador tem sobre o tipo de algo é menos específico do que o que você sabe (ou pelo menos espera).
Em situações como o seu exemplo, o objeto foi criado como um Applee, em seguida, esse conhecimento foi descartado, armazenando a referência em uma variável do tipo Fruit. Então você deseja usar a mesma referência que Appleoutra vez.
Como as informações foram descartadas apenas "localmente", com certeza, o compilador pode manter o conhecimento que parenté realmente um Apple, mesmo que seu tipo declarado seja Fruit.
Mas geralmente ninguém faz isso. Se você deseja criar Applee usá-lo como Apple, armazene-o em uma Applevariável, não em uma Fruit.
Quando você tem um Fruite deseja usá-lo como um Apple, geralmente significa que você obteve Fruitalguns meios que geralmente poderiam retornar qualquer tipo de Fruit, mas, nesse caso, você sabe que era um Apple. Quase sempre você não apenas o construiu, foi aprovado por algum outro código.
Um exemplo óbvio é se eu tenho uma parseFruitfunção que pode transformar seqüências de caracteres como "maçã", "laranja", "limão" etc. na subclasse apropriada; geralmente todos nós (e o compilador) pode saber sobre esta função é que ele retorna algum tipo de Fruit, mas se eu chamar parseFruit("apple"), em seguida, eu sei que vai chamar um Applee pode querer usar Applemétodos, para que eu pudesse abatido.
Novamente, um compilador suficientemente inteligente pode descobrir isso aqui, incorporando o código-fonte parseFruit, pois estou chamando-o com uma constante (a menos que esteja em outro módulo e tenhamos compilação separada, como em Java). Mas você deve poder ver facilmente como exemplos mais complicados envolvendo informações dinâmicas podem se tornar mais difíceis (ou até impossíveis!) Para o compilador verificar.
Em códigos realistas, os downcasts geralmente ocorrem onde o compilador não pode verificar se o downcast é seguro usando métodos genéricos, e não em casos simples, como imediatamente após um upcast jogar fora as mesmas informações de tipo que estamos tentando recuperar por downcasting.