Há como esconder ou suprimir métodos públicos herdados?

As vezes quero fazer herança de classes que facilitam a implementação de uma classe como certas estruturas de dados, mas os métodos públicos dessa classe vêm junto na herança.
Seria bom tirar vantagem da herança e ao mesmo tempo criar uma classe limpa e com poucos métodos, facilitando o entendimento da mesma.

Gostaria de saber se é possível evitar a herança de determinados métodos e atributos ou pelo menos escondê-los.

Olá amigo, quando você usa da herança. Em java um método herdado não pode ser sobrescrito de forma mais restritiva, public nao pode ser protected, e protected nao pode ser private ou defaul.

para conseguir Usar os métodos que são pertinentes porem inibir o acesso a outros métodos desnecessario. É mais pratico vc criar uma Interface e implementar essa interface,onde a classe implementadora vai “ter uma instancia da classe que possui os métodos que são pertinentes pra você”.

Na minha opinião, eu implementaria assim.
Fica a dica
Fallow Abraço

É mais ou menos isso que eu faço, embora não faça necessariamente através de interface, eu costumo criar um atributo e delego os métodos dele.

No entanto o que me incomoda um pouco é o fato de que isso é um meio que uma gambiarra, ou pelo menos não é uma boa prática de orientação a objetos. Porque se um objeto é um tipo de outro objeto, deve usar herança e não conter o objeto do tipo mais genérico.

bem questionável essa afirmação sua. Muitos autores (entre eles erich gamma) defendem que a herança não é uma boa prática pois quebra o encapsulamento.

No clássico padrões de projeto: soluções reutilizáveis de software OO a gang dos 4 é clara: “prefira composição no lugar de herança”

Em ultima instancia vc pode sobrepor seus métodos herdados por outros com corpo vazio.

há alguns vários topicos atras o cv disse algo que era ± assim:

Entao, se voce notou algum problema de encapsulamento na sua heranca, talvez o problema nao seja da heranca mas sim do seu design. Interfaces caem muito bem nesta situacao e dependendo da situacao, o padrao Adapter pode te ajudar.

não tem essa de “sua herança”. Sem conhecer profundamente o código fonte da classe mãe, fica impossível de que essa classe filha funcione corretamente ao reescrever um método que é aparentemente inofensivo.

sugiro a leitura do artigo “Encapsulation and Inheritance in Object-Oriented Programming Languages” do ano de 1986

Boa tarde a todos.

Nem tanto assim. Acho que tanto a herança quanto a composição tem suas vantagens e desvantagens cada uma. Dependendo do desenvolvimento de sua aplicação, voce pode utilizar a herança ou a composição, ou até ambas.

Optar somente por composição, para mim então seria melhor retroagir a linguagem de programação estruturada.

Imagine voce ter que reescrever uma classe que monta uma janela da GUI, ou voce ter que reescrever todos os métodos comuns de uma classe do tipo Socket para enviar dados na Web. Ter que reelembrar todos os seus métodos e atributos seria um caos, mesmo o java sendo open source.

Além disso, discordo quando diz que herança quebra o encapsulamento, se assim fosse, para serviria os modificadores “private” e “protected”.

Contudo, se voces repararem, até dentro da composição de objetos entre classes existe a herança. Como assim :?: :?: :?:

Não existe classe sem classe pai, mãe, super classe, classe descendente ou como queiram chamar, isto porque todas as classes do java extende (herda) de Object implicitamente, isto quer dizer que mesmo voce declarando uma classe de modo simples omitindo qualquer herança (extenção), queira ou não queira ela vai herdar de Object.

Assim é também na linguagem Object Pascal do Delphi que tem a classe TObject como classe primária, logo não dá para escapar da herança, até porque ela não tão ruim assim.

Um abraço.

não tem essa de “sua herança”. Sem conhecer profundamente o código fonte da classe mãe, fica impossível de que essa classe filha funcione corretamente ao reescrever um método que é aparentemente inofensivo.

sugiro a leitura do artigo “Encapsulation and Inheritance in Object-Oriented Programming Languages” do ano de 1986[/quote]

Há um problema na classe mãe afetando o design? Sugiro a leitura de FOWLER, Martin e cia - REFACTORING de 1999

Nao tem segredo, na maioria esmagadora das vezes o problema é no design. Se existe um método na classe mãe que nao deve estar nas filhas: 1 - este metodo deve sair da classe mae e ir para uma classe isolada - 2 - deve existir uma interface que defina a acao deste metodo - 3 as classes que precisam deste metodo podem implementar a interface - 4 - a implementacao da interface pode ser usando a classe que recebeu a extracao do metodo e por ai vai.

E se nao tem como alterar o codigo da classe mae, ainda eh possivel adapta-lo com composicao e um leve padraozinho ja dito:

[code]class MeuSuperAdapter {
private AquelaClasseMae mae = new …;

public void metodoIndispesavel() {
mae.metodoIndispensavel();
}

public Xpto outroMetodoQueQueria(String x) {
return mae.outroMetodoQueQueria(x);
}
etc.
}

class Filho extends MeuSuperAdapter {

}[/code]

Acho que a discussão ficaria bem mais interessante se você citasse um exemplo de onde isso seria útil. Se uma subclasse restringir métodos da superclasse então ela está quebrando a interface da superclasse. Daí obtemos uma contradição: se a subclasse quebra o contrato de operação da superclasse então não deve haver relacionamento do tipo É-UM entre elas. Eu não seria categórico em afirmar que composição é a solução para o problema, talvez seja o caso de dividir a superclasse em uma ou mais classes e aplicar a herança nas classes que interessa. Mas definitivamente, restringir acesso de membros da superclasse não é o caminho.

Enfim, o artigo abaixo é ótimo e resume toda a discussão:

http://blog.caelum.com.br/como-nao-aprender-orientacao-a-objetos-heranca/

ou seja: você PRECISA conhecer a implementação da classe mãe

pra você que também é fã do Fowler fica o artigo:

http://martinfowler.com/bliki/DesignedInheritance.html

Não implementar métodos da super classe é um mau cheiro, chamadode “Herança negada”.
Ter um pouco disso no sistema não é incomum, o java mesmo implementa wrappers para listas que as tornam imodificáveis através de herança negada.

Mas de qualquer forma, é um indício forte de que alguma coisa não está indo bem no seu design.
Geralmente, ou você deve usar composição (e ela deve ser preferida sobre herança), ou você deverá redividir suas classes, como citou o rmendes.

Só a título de comparação: Minhas hierarquias de classes muito difícilmente ultrapassam 2 níveis de altura, sendo o mais comum apenas um objeto com seu pai. Não estou adicionado interfaces na conta.
Essas sim, o sistema possui várias.

[quote=orlandocn][quote=peerless]
Há um problema na classe mãe afetando o design? Sugiro a leitura de FOWLER, Martin e cia - REFACTORING de 1999
[/quote]

ou seja: você PRECISA conhecer a implementação da classe mãe

pra você que também é fã do Fowler fica o artigo:

http://martinfowler.com/bliki/DesignedInheritance.html[/quote]

em que momento eu disse que não?

Vou citar um exemplo de onde poderia usar herança negada.

Suponha que eu tenha uma classe Vertice. Essa classe tem como atributos coordenadas x e y e os respectivos métodos de acesso mais o método public void set(double x, double y).

Eu quero extendê-la para ter uma classe Vertice3D. É evidente que a Vertice3D terá os mesmos atributos e métodos de Vertice, mais o atributo z e os métodos de acesso de z. Mas eu não quero ter nesta classe o método public void set(double x, double y) por motivos óbvios.

Outro exemplo é uma classe ArrayTable que é uma classe que contém um array bidimensional e métodos de acesso aos valores de cada linha e coluna. É uma facilidade para não ter que ficar implementando arrays bidimensionais o tempo todo.

Suponham que eu quero criar a classe SetTable que é um ArrayTable onde cada campo tem um conjunto e ao invés manipular os campos do array eu quero manipular os objetos do conjunto com os métodos de acesso. Por exemplo, o método public void set(int x, int y , Object value) adicionaria um elemento na posição xy do ArrayTable ou adicionaria um objeto no conjunto da posição xy no caso do SetTable. Até ai tudo bem, posso sobrescrever o método.

Mas vamos supor que a classe ArrayTable permite adicionar ou remover linhas e colunas da tabela através dos métodospublic void addLine(){...} public void addRow(){...} e eu quero que o SetTable tenha um tamanho estático durante toda a sua execução. Nesse caso a herança negada seria muito útil para impedir o redimensionamento da tabela.

Outra dúvida é em relação ao uso de associação no lugar de herança para classes do tipo final como a Classe String.

Não me parece que um Vertice3D seja um Vertice2D. Como a relação é um falha, não há sentido em herança.

Não haveria sentido em fazer:

Vertex2D v2d = new Vertex3D(10,20,30); 

Faria? Claramente, não é um caso de herança.

Não daria para inverter a herança? O ArrayTable ser o filho? Nesse caso, o pai não teria o método set, e o ArrayTable seria só um caso redimensionável do pai.
Caso contrário, seria um caso onde ou eu usaria herança negada mesmo.

No caso dos vértices o objetivo e seria o de escrever menos código, mas o que você disse faz sentido.

O ArrayTable tem valores mais genéricos em seus campos. O TableSet (Tabela de conjuntos, se o meu péssimo inglês não me trai) sempre tem conjuntos em seus campos. Então não pode ser o contrário. O TableSet tem que herdar de ArrayTable.

Dei uma olhada no link da Caelum postado acima e acho que a melhor maneira de fazer o que quero seria criar uma interface com tudo o que as duas classes tem em comum e depois fazer as duas classes implementarem essa interface.

Mas ainda assim gostaria de saber se criar uma interface que tem um objeto da classe final como atributo e usar delegação de métodos seria uma maneira correta para extender classes final (como a classe String por exemplo).

Pois é, no começo vemos a herança como uma forma de poupar código. Mas herança não é isso. Herança estabelece uma relação semântica entre classes que diz que uma é um exemplo mais especializado de outra.