O uso mais comum de tais subclasses que eu posso imaginar são as hierarquias de exceção, embora seja um caso degenerado em que normalmente não definimos nada na classe, desde que a linguagem nos permita herdar construtores. Usamos herança para expressar que ReadError
é um caso especial de IOError
e assim por diante, mas ReadError
não precisa substituir nenhum método de IOError
.
Fazemos isso porque exceções são capturadas ao verificar o tipo delas. Assim, precisamos codificar a especialização no tipo para que alguém possa capturar somente ReadError
sem capturar todos os IOError
, caso deseje.
Normalmente, verificar os tipos de coisas é terrivelmente mal e tentamos evitá-las. Se conseguirmos evitá-lo, não há necessidade essencial de expressar especializações no sistema de tipos.
Ele ainda pode ser útil, por exemplo, se o nome do tipo aparecer no formulário de string registrada do objeto: isso é linguagem e possivelmente estrutura específica. Você poderia, em princípio, substituir o nome do tipo em qualquer sistema com uma chamada para um método da classe, caso em que substituiríamos mais do que apenas o construtor em SystemDataHelperBuilder
, também substitui loggingname()
. Então, se existe algum registro em seu sistema, você pode imaginar que, embora sua classe literalmente apenas substitua o construtor, "moralmente" também está substituindo o nome da classe e, para fins práticos, não é uma subclasse apenas de construtor. Ele tem um comportamento diferente desejável, é apenas que você obtém esse comportamento de graça, sem escrever nenhum método, graças a um uso inteligente da reflexão em outro lugar.
Então, eu diria que o código dele pode ser uma boa idéia se houver algum código em outro lugar que de alguma forma verifique as instâncias de SystemDataHelperBuilder
, explicitamente com uma ramificação (como a exceção capturando ramificações com base no tipo) ou talvez porque haja alguma código genérico que acabará usando o nome SystemDataHelperBuilder
de uma maneira útil (mesmo que seja apenas o registro).
No entanto, usar tipos para casos especiais gera alguma confusão, pois se ImmutableRectangle(1,1)
e ImmutableSquare(1)
se comportarem de maneira diferente de alguma forma , eventualmente alguém se perguntará por que e talvez deseje t. Ao contrário das hierarquias de exceção, você verifica se um retângulo é um quadrado verificando se height == width
, não com instanceof
. No seu exemplo, há uma diferença entre um SystemDataHelperBuilder
e um DataHelperBuilder
criado com os mesmos argumentos exatos e que tem potencial para causar problemas. Portanto, uma função para retornar um objeto criado com os argumentos "certos" parece-me normalmente a coisa certa a fazer: a subclasse resulta em duas representações diferentes da "mesma coisa", e só ajuda se você estiver fazendo algo que você normalmente tentaria não fazer.
Note que eu não falo em termos de padrões de design e antipadrões, porque não acredito que seja possível fornecer uma taxonomia de todas as boas e más idéias que um programador tem já pensou. Assim, nem toda idéia é um padrão ou antipadrão, só se torna quando alguém identifica que ela ocorre repetidamente em contextos diferentes e a nomeia ;-) Eu não tenho conhecimento de nenhum nome particular para esse tipo de subclasse.