Quanto mais aprendo sobre diferentes paradigmas de programação, como programação funcional, mais começo a questionar a sabedoria dos conceitos de POO, como herança e polimorfismo. Eu aprendi sobre herança e polimorfismo na escola e, na época, o polimorfismo parecia uma maneira maravilhosa de escrever código genérico que permitia fácil extensibilidade.
Mas diante da digitação do pato (dinâmica e estática) e dos recursos funcionais, como funções de ordem superior, comecei a considerar a herança e o polimorfismo como impondo uma restrição desnecessária com base em um conjunto frágil de relacionamentos entre objetos. A idéia geral por trás do polimorfismo é que você escreve uma função uma vez e, posteriormente, pode adicionar novas funcionalidades ao seu programa sem alterar a função original - tudo que você precisa fazer é criar outra classe derivada que implemente os métodos necessários.
Mas isso é muito mais simples de se obter através da digitação de pato, seja em uma linguagem dinâmica como Python ou em uma linguagem estática como C ++.
Como exemplo, considere a seguinte função Python, seguida pelo seu equivalente estático em C ++:
def foo(obj):
obj.doSomething()
template <class Obj>
void foo(Obj& obj)
{
obj.doSomething();
}
O equivalente a OOP seria algo como o seguinte código Java:
public void foo(DoSomethingable obj)
{
obj.doSomething();
}
A principal diferença, é claro, é que a versão Java requer a criação de uma interface ou hierarquia de herança antes de funcionar. A versão Java, portanto, envolve mais trabalho e é menos flexível. Além disso, acho que a maioria das hierarquias de herança do mundo real é um pouco instável. Todos nós já vimos exemplos inventados de Formas e Animais, mas, no mundo real, à medida que os requisitos de negócios mudam e novos recursos são adicionados, é difícil realizar qualquer trabalho antes que você realmente precise ampliar o relacionamento "é um" entre subclasses ou remodele / refatorar sua hierarquia para incluir outras classes-base ou interfaces para acomodar novos requisitos. Com a digitação do duck, você não precisa se preocupar em modelar nada - apenas se preocupa com a funcionalidade necessária.
No entanto, herança e polimorfismo são tão populares que duvido que seria exagero chamá-los de estratégia dominante para extensibilidade e reutilização de código. Então, por que a herança e o polimorfismo são tão bem-sucedidos? Estou negligenciando algumas vantagens sérias que a herança / polimorfismo tem sobre a digitação de patos?
obj
não tivesse umdoSomething
método? Uma exceção é levantada? Nada acontece?