Estou montando um projetinho, que possui as seguintes entidades: Cliente, Vendedor e Fornecedor.
Eu queria usar herança para estas entidades, fazendo com que estas extendem os atributos em comum, da classe pai, que seria Usuario.
Porém, o Cliente é o único que não se loga no sistema, logo, ele não precisa de login nem senha, mas os demais sim.
public abstract class Usuario extends Pessoa(){
private String login;
private String senha;
}
public class Vendedor extends Usuario(){
}
public class Fornecedor extends Usuario(){
}
public class Cliente extends Pessoa(){
}[/code]
Algo desse tipo?
É pq eu vou jogar os annotations do Hibernate pra mapear as entidades, teria algum exemplo de uma implementação dessa usando Hibernate?
Existem dois motivos para se usar herança, o mau e o bom. O mau motivo é usar herança pra fazer reuso de código: “bem, se estas duas classes aqui têm um método calculatePrice()” que é igual, então vou criar uma classe base AbstractPriceable e botar o método nela!!".
Este é um mau motivo porque você acopla duas classes que não deveriam ter nada a ver uma com a outra. Só se deve fazer herança quando houver uma relação “É-UM”. Um exemplo de livro-texto: você pode ter a classe base Shape, e a classe filha Circle extends Shape. Isso porquê Circle “É-UM” Shape E você tem situações legítimas onde você quer trabalhar com objetos Shape de maneira genérica sem se importar se ele é um Circle, Square ou Rectangle – apesar de que eu prefereria usar interfaces neste caso.
No seu exemplo, a princípio parece fazer sentido que Cliente “É-UM” Usuario.
Mas será que Usuario é realmente a abstração em comum de Cliente, Vendedor e Fornecedor? Você mesmo diz que Cliente não se loga no sistema. Acho que você está escolhendo a abstração errada para a classe base. Há situações onde você precisa usar a classe Usuario de maneira genérica, não importando se a classe concreta é Cliente, Vendedor ou Fornecedor? Mesmo que a resposta for SIM, você pode considerar usar interfaces ao invés de herança.
Quanto a esse exemplo aí, se resolver fazer assim tome cuidado como vai mapear no Hibernate, porque você pode acabar com Clientes, Vendedores e Fornecedores todos misturados na tabela PESSOA. Provavelmente ficaria mais limpo se você tivesse as tableas CLIENTE, VENDEDOR E FORNECEDOR OU talvez uma tabela CLIENTE e outra USUARIO onde USUARIO pode ser Vendedor ou Fornecedor. Me parece fazer mais sentido. \Outra coisa, usar herança apenas para reusar os campos id e nome me parece desnecessário.
public abstract class Usuario extends Pessoa(){
private String login;
private String senha;
}
public class Vendedor extends Usuario(){
}
public class Fornecedor extends Usuario(){
}
public class Cliente extends Pessoa(){
}[/code]
Algo desse tipo?
É pq eu vou jogar os annotations do Hibernate pra mapear as entidades, teria algum exemplo de uma implementação dessa usando Hibernate?
Felipe, na minha opinião o que você deve levar em consideração quando for usar herança é se seu objeto realmente “É UM” tipo do outro. Por exemplo: Pergunte a você mesmo se seu Vendedor é um Usuário ou se em determinados momentos ele se comporta ou assume papel de um. Neste caso vejo como melhor alternativa o uso de Composição para compartilhar os atributos em comum e como seu objeto Vendedor e Fornecedor assumem papel de um Usuário, você deveria criar um interface Usuário e fazer com que seu Vendedor e seu Fornecedor implementem ela, aproveitando assim o poder do polimorfismo.
E costumo pensar em herança não definindo uma superclasse para classes, mas sim uma subclasse para as classes.
A diferença é que você acaba pensando em especialização e não em generalização. Dá mais certo.
Por esse lado, olhando superficialmente, Vendedor, Fornecedor e Cliente fazem parte de uma mesma parte do sistema, Vendas, mas Usuário não tem nada a ver com isso. Também não importa que Vendedor, Fornecedor, Cliente e até mesmo Usuário herdem de Pessoa. Por acaso eles não não podem ser Empresas? Não me venha com “Empresa é Pessoa Jurídica”. A venda pode ser para um grupo de pessoas, sem PJ. Vai obrigar elas a usarem CPF ou CNPJ p/ poder executar a venda? Perdeu um cliente.
Se dois deles são usuários, por que não nomeá-los UsuárioVendedor, UsuárioFornecedor? Aí sim seriam especializações de Usuário.
Cara, sinceramente, o único momento que eu usaria a classe Usuario de maneira genérica, seria na autenticação, já que eu não sei quem está logando, mas quanto ao cliente, de fato só pensei em herança justamente pra reuso.
Não são somente estes campos, coloquei só pra exemplificar.
O uso de interfaces poderia ser uma boa solução, assim como o Domingos falou. O Hibernate suporta essa hierarquia?
[quote=Bruno Laturner]E costumo pensar em herança não definindo uma superclasse para classes, mas sim uma subclasse para as classes.
A diferença é que você acaba pensando em especialização e não em generalização. Dá mais certo. [/quote]
Bruno, teria como me dar um exemplo bem simples? Não acompanhei a linha de raciocínio
[quote=felipempantoja]Estou montando um projetinho, que possui as seguintes entidades: Cliente, Vendedor e Fornecedor.
Eu queria usar herança para estas entidades, fazendo com que estas extendem os atributos em comum, da classe pai, que seria Usuario.
Porém, o Cliente é o único que não se loga no sistema, logo, ele não precisa de login nem senha, mas os demais sim.
Alguém teria uma sugestão para este probleminha? [/quote]
Felipe, utilizar herança para reaproveitar atributos é uma péssima ideia. Pra avaliar o uso de uma herança correta você precisa pensar em espaço-estado, invariantes, pré/pós condições, e uma série de outras coisinhas pra não correr o risco de fazer uma bela cagada no design da sua aplicação.
Na verdade não foi uma herança única e exclusivamente para reaproveitar atributos, eu acredito que realmente faça sentido o uso da herança neste modelo de classes, já que um Usuário (usuário do sistema) é uma Pessoa, assim como Cliente é uma Pessoa, e indo mais além, um Vendedor e um Fornecedor pertencem a classe Usuario, já que ambos acessam o sistema.
Eu li um pouco nos últimos dias sobre o uso da composição ao invés da herança, a questão é, se é possível usar composição com Hibernate
Procurei alguma coisa na internet porém, sem sucesso.
Na verdade não foi uma herança única e exclusivamente para reaproveitar atributos, eu acredito que realmente faça sentido o uso da herança neste modelo de classes, já que um Usuário (usuário do sistema) é uma Pessoa, assim como Cliente é uma Pessoa, e indo mais além, um Vendedor e um Fornecedor pertencem a classe Usuario, já que ambos acessam o sistema.[/quote]
A forma de você definir esse E-UM não pode ser simplesmente baseado na intuição. Dá uma lida em [Page-Jones, 1999] que explica bem sobre o assunto. Na internet tem material mais básico sobre o assunto tb.
[quote=felipempantoja]Eu li um pouco nos últimos dias sobre o uso da composição ao invés da herança, a questão é, se é possível usar composição com Hibernate
Procurei alguma coisa na internet porém, sem sucesso.[/quote]
A annotation @Embedded talvez te ajude.