[MÚSICA] [MÚSICA] Olá, bem vindo ao Curso Desenvolvimento Ágil com Padrões de Projeto! Eu sou o Clovis Fernandes. Ao final desta aula você aprenderá como não usar herança. Vocês já sabem como usar herança. Usam normalmente no dia-a-dia, mas existem alguns pequenos problemas que nós vamos tornar claro nesta aula. Entenda o perigo do uso inadequado da herança. Vamos supor que você tenha uma classe Grilo, por exemplo, que tem duas responsabilidades expressas pelos seus métodos: mover e pular. Poderia ter outros. Vamos imaginar também que o método mover é muito complicado de se fazer e o método pular é simples. Então, eu fico com aquele pequeno problema: cara, eu tenho método aqui que vai ser muito complicado desenvolver. Será que eu consigo reusar método mover de alguma outra classe? Seria muito mais fácil, eu já aproveito e reuso. Uma maneira de fazer isso é através do reuso por herança. Por acaso, existe uma classe numa biblioteca qualquer, que seria a classe Aranha que eu tenho lá o método mover. Tem outros métodos como, por exemplo, fazer teia. O método mover da aranha é exatamente o que eu quero para a classe grilo. Então, eu faço a classe grilo, eu estou criando nesse momento, ser subclasse da classe aranha e aí eu vou herdar o método mover, naturalmente. Então, eu vou ter reuso por herança. O método pular é específico da classe e é simples de fazer, na nossa hipótese. Como eu vou herdar da outra classe, eu não preciso apresentar o método mover representado na minha classe Grilo, mas toda a vez que eu criar objeto Grilo, eu posso mandar a mensagem mover para esse objeto Grilo. Agora, prestem atenção que na classe Aranha há outros métodos. No caso, eu estou só exemplificando com o método público 'fazerTeia'. E o que que acontece com esse método público 'fazerTeia'? Ele também é herdado pela classe Grilo. Então, esse é dos problemas que a gente tem com esse tipo de herança. A gente chama que é uma herança por construção: eu queria realmente reusar alguma coisa que é muito importante para mim, mas eu herdo também todas as outras coisas que não são importantes para aquela classe. O quê que eu tenho que fazer, então? Na classe Grilo, ela vai herdar. Não faz sentido o grilo fazer teia, quem faz teia é a aranha. Então, eu sobreponho o método fazer teia na classe Grilo e, por exemplo, deixo-o vazio, não faço nada. Eu poderia também escrever uma mensagem para sair esse método: 'fazerTeia' não deve ser usado ou lançar uma exceção. No nosso exemplo, nós vamos usar não fazer nada. Aí surge a pergunta: então, é assim que a gente faz herança? Não! Essa imagem que vocês estão vendo aqui não tem nada a ver com isso, mas mostra o desespero quando a gente vê código que tenha uma herança que eu chamei por construção, que eu apenas, de uma forma oportunista, estava querendo reusar ou mais métodos, mas ao mesmo tempo eu herdo monte de outros métodos. Eu tenho que fazer isso tudo que eu fiz: sobrepor e fazer alguma coisa. No meu exemplo, no 'fazerTeia', eu estou colocando como código vazio, não faz nada. Vamos reafirmar isso: não é assim. Não é assim que se faz herança. Herança por construção não é uma coisa boa, deve ser evitada. Vamos exemplificar aqui, mostrando que como a classe Grilo é subclasse da classe Aranha, supostamente objetos Grilos poderão substituir objetos Aranhas. Não deveria dar problema algum. Mas aí é que está, dá problema, porque o objeto Grilo, ele herda algumas responsabilidades, alguns métodos da classe Aranha que não fazem sentido para ele. Isso pode dar algum problema nos códigos que envolvam variáveis do tipo Aranha que você está substituindo, colocando objeto Grilo. Vamos começar supondo, então, que eu estou criando aqui objeto Aranha. Então, eu ponho Aranha igual a new Aranha que vai pegar alguma presa e eu vou usar como parâmetro de método, outro método, que é o de captura, ele captura. A aranha vai capturar uma presa, eu passo os dois parâmetros: aranha e presa. Presa, qualquer animalzinho que possa ser pego pela aranha. Vamos imaginar agora o código dessa captura. Eu passo objeto Aranha e tem loop ali: enquanto a presa não se encontra dominada ou presa numa teia de aranha, eu vou lá e peço para a aranha criar a teia. Após a aranha criar a teia, o objeto vai ficar preso na teia e eu saio fora do loop naturalmente. Como a aranha é natural para ela o método 'fazerTeia', não há problema nenhum aqui e o código flui normalmente. Agora vamos imaginar uma situação que eu tenha objeto Grilo que seria do tipo Aranha, que eu ponho Grilo igual a new Grilo. Não tem problema nenhum, porque Grilo é subclasse de Aranha. E vou fazer a mesma coisa, eu vou passar isso agora como parâmetro. Então, eu estou passando agora o Grilo como parâmetro. Então, o quê que vai ocorrer agora? No loop, agora é objeto Grilo, o parâmetro passado é do tipo Aranha, mas eu posso passar objetos de subclasses, polimorfismo, certo? Passei, agora o objeto é Grilo. Então, quando eu faço Grilo 'fazerTeia', ele não faz teia e esse loop, então, fica loop infinito. Ou seja, não é assim que se faz herança. Esse tipo de herança que a gente chama de herança por construção, que é uma coisa oportunista, só para aproveitar alguns métodos que são complicados de fazer e você não quer repetir e construí-lo novamente, não é uma boa coisa. Nós vimos então que não se deve usar herança por construção. Você vai incorrer muitos erros e nas próximas aulas nós iremos mostrar como fazer uso apropriado e, mais para a frente numa outra aula, como fazer o uso da composição que, alguns casos, só a herança não é suficiente ou apropriada, a herança adequada, aí você faz uma composição. Obrigado! [MÚSICA] [MÚSICA]