Propriedade privada, herda ou não herda?

A subclasse herda, mas existirão dois métodos em escopos diferentes. Um na superclasse e outro na subclasse.

Um jeito fácil de demonstrar tudo isso é usar reflexão. Pegue um objeto de uma subclasse, faça reflexão em todos os níveis de sua hierarquia e você vai ver que está tudo lá, nada foi apagado. Como o Dieval ressaltou, todo objeto de uma subclasse “é uma” instância da superclasse, então, mesmo que não esteja acessível ela terá a parte privada do seu pai.

O importante é não confundir a inexistência de um método ou atributo (que ocorreria se ele não fosse herdado), com a incapacidade de acessa-lo (regra de escopo).

se no exame da SCJP cair alguma questao com este problema…

o q eu marco?!

  1. O q o pessoal estaá achando aki no topico (eu tb achava - ou será q ainda acho?! :? )?
  2. O q a Kathy escreveu no livro ?

:?

Herda??? é visivel???
na real, qual a diferença??
como ja foi explicado N vezes no topico. herda, mas não pode ser usado diretamente por causa do escopo de visibilidade. isso é um detalhe que NUNCA interfereriu na minha vida. tem coisas mais importantes na linguagem p/ se preocupar.
p/ a prova marque SEMPRE que não herda. o livro da Kathy é bem claro, ele não ensina Java, ensina a passar na prova, é o que ela faz e MUITO bem.

[]´s

[quote=ViniGodoy]A subclasse herda, mas existirão dois métodos em escopos diferentes. Um na superclasse e outro na subclasse.

Um jeito fácil de demonstrar tudo isso é usar reflexão.[/quote]

Relexão não é jeito de provar coisa nenhuma porque com reflexão vc pode até acessar métodos privados de outras classes.
Reflexão viola declaradamente o encapsulamento e as formas de polimorfismo. Ela faz isso de propósito, não é um erro.
Cuidado em dizer que reflexão prova alguma coisa, porque não prova. Ela foi criada exatamente para subverter as regras do compilador.

O fato da reflexão acessar aos método privados prova que ela viola as regras padrão dos modificadores de visibilidade
e isso significa que ela não pode ser usada para demonstrar como os modificadores funcionam. A mesma coisa se aplica a herança.
Métodos que manipulam metadados não podem ser usados para provar as regras a que os dados são sujeitos.

Outro exemplo: Java não permite herança multipla, mas o bytecode permite. Ferramentas de reescrita de bytecode permitem criar objetos que pertencem a duas classes simultanetamente, mas isso não significa que a linguagem java permite herança multipla.

Por outro lado o fato do método da super-classe existir no bytecode da subclasse também não prova que ele é herdado. Na realidade o codigo nem está na subclasse. Apenas parece estar. Se falarmos de attributos, claro que todos estão em todos os objetos da classe, mas isso não prova que ha herança de atributos privados.

Herança é apenas um mecanismo para expandir a visibilidade de métodos (aumentar o escopo). E por isso temos modificadores para restringir essa visibilidade. Herança não é um mecanismo de implementação é algo abstrato e conceptual: são regras.
Cada linguagem é livre de implementar os mecanismo como quiser.

Quando se fala que A extends B estamos espandindo o escopo de classe de B para A. Por padrão tudo é herdado de B para A, ou seja, por padrão todos os métodos de B são visiveis a A. Mas e se não queremos que isso seja verdade. Como restringir a herança ? como dizer que o método xxx não pode ser visivel por A, ou seja, como fazer para que xxx não seja herdado ?
Declarar que ele é privado. Só isso. Ser privado é exactamente dizer que não é herdado. É um despropósito dizer que o que é privado é herdado quando é exactamente para impedir isso que “private” existe.

Outra coisa que precisa ser lembrada é que as regras de visibilidade são reforçadas pelo compilador. Uma vez em runtime essas regras são inúteis (dai ser possível a reflexão, porque ela contece em runtime). As regras impostas pelo compilador são aquilo que compõe a linguagem java. Na linguagem java coisas privadas não são herdadas. Esse é o inteiro propósito delas serem privadas! É a restrição máxima do escopo que a herança cria. Também na linguagem java não ha multipla herança de classes.
Na plataforma java não existem restrições. Isso permite API de Reflection e manipulação de Bytecode que fazem coisas que o programador não pode fazer usando as regras normais. Por isso que são Meta-API elas fazem coisas além (meta) do normal.
Também, por isso a plataforma Java permite que outras linguagens sejam usada para geram bytecode.

Enfim ,essa conversa de que coisas privadas são herdadas não faz sentido nenhum. Basear-se na API de reflexão ou na estrutura de memória não prova nada, porque essas coisas não obedecem as mesmas regras.

Resumindo:
1)Linguagem Java e a Plataforma Java não são a mesma coisa. Têm regras diferentes.
2)API de Reflexão e manipulação de bytecode funcionam ao nivel da plataforma e não da linguagens. (Por isso se usam classes e não um sintaxe qq especial) Como tal, não podem ser usadas para provar ou desaprovar regras da linguagem. (é como dizer que grovy não tem closures porque não existem em java. Essa conversa não tem sentido)
3) Herança é uma conjunto de regras para aumentar o escopo de visibilidade dos membros da classe. Tornar as coisas privadas é negar que esse escopro aumente para aquele membro em especifico. Herança não é uma mecanismo ou uma forma de implementação. É algo que a linguagem java tem e que a plataforma java implementa. A prova que as regras da linguagem e da plataforma são diferentes é que a primeira não permite herança multipla, mas a segunda sim.
4) Dizer que coisas privadas são herdadas não faz sentido, pois “private” existe apenas para negar que o membro seja herdado (i.e. seja visivel às classes filhas).

So pra contradizer melhor o exemplo do CPF do pai e do filho aqui vem um exemplo:

class Pessoa {
	private String nome;
	public String getNome() { return nome; }
	public void setNome(String nome) { this.nome = nome; }
}
class Funcionario {
	private String empresa;
}

Nossa… Uma pessoa tem um nome… um funcionario não! ???
Pra mim, a relacao de classe nao eh tipo… pai pra filho como alguns dizem.
Que eu saiba a relacao é do famoso “é um”.
Funcionario é uma Pessoa, logo Funcionario tem um atributo nome.

Herança não tem nda a ver com a linguagem , herança tem a ver com conceitos de OO !

Tentem desvincular o conceito OO e a linguagem …

[quote=goofed]So pra contradizer melhor o exemplo do CPF do pai e do filho aqui vem um exemplo:

class Pessoa {
	private String nome;
	public String getNome() { return nome; }
	public void setNome(String nome) { this.nome = nome; }
}
class Funcionario {
	private String empresa;
}

Nossa… Uma pessoa tem um nome… um funcionario não! ???
Pra mim, a relacao de classe nao eh tipo… pai pra filho como alguns dizem.
Que eu saiba a relacao é do famoso “é um”.
Funcionario é uma Pessoa, logo Funcionario tem um atributo nome.[/quote]

Pelo o que eu entendi…através da herança - conceito OO, funcionário tem NOME sim…mas na linguagem java Funcionario não herda a propriedade nome diretamente, porém, ele acessa a propriedade através dos metodos get/set e a linguagem se encarrega de fazer essa ‘assossiacao’ entre as classes…de modo que o conceito herança seja aplicado…

certo pessoal?! :?

Quem tiver tempo, faça download do BlueJ (http://www.bluej.org/index.html)
A resposta esta la !

So pra adiantar, metodos privados são herdados !

Acreditam que eu tava estudando o Heads First Java e li que não herdam e perguntei no Javaranch?
Não herdam explicitamente, mas com métodos set e get posso acessá-los tranquilamente.

Ps.: PM, o que o BlueJ tem a ver? Eu tenho ele (na verdade acho que é a melhor IDE pra se aprender java, sinceramente) e aconselho pra muita gente. Vale muito a pena pra aprender.

O BlueJ é uma das melhores ferramentas para aprender OO.

Cria as duas classes uma Pai e outra filho.
Criar um atributo privado na Pai e depois cria uma instancia da filho.
Olha as “propriedades”(inspect) da objeto e ae vc vai ver que ele herda o atributo privado da classe Pai.

simples assim !

Herdar é diferente de acessar !!
Neste caso, gets e sets tem haver com polimorfismo !

O que eu fiz… criei uma classe pessoa…

public class Pessoa {

public String nome = "Nome de Pessoa";
public String sexo = "Sexo de Pessoa";
private String RG;
private String CPF;

}

depois fiz a seguinte classe estendendo de pessoa…

public class Carlos extends Pessoa {

public Carlos(){
}

public static void main(String[] args){
Pessoa p = new Pessoa();
Carlos c = new Carlos();
		
}
}

no eclipse em modo debug acontece o seguinte:(eu não consegui colocar a imagem mais seria isso)

p = Pessoa
CPF = null
nome = “Nome de Pessoa”
RG = null
sexo = “Sexo da Pessoa”

c = Carlos
CPF = null
nome = “Nome de Pessoa”
RG = null
sexo = “Sexo da Pessoa”

seguindo esse raciocinio… acho que herda sim, porém não há visibilidade, como já foi dito.

é só minha humilde opnião…

[quote=pm][quote=dedejava]
Não herdam explicitamente, mas com métodos set e get posso acessá-los tranquilamente.
[/quote]

Herdar é diferente de acessar !!
Neste caso, gets e sets tem haver com polimorfismo !
[/quote]

Polimorfismo? Por que? Não teria mais haver com encapsulamento?
Eu acesso a variavel de instância pela subclasse e não pela superclasse. Mesmo se eu usasse o polimorfismo, fazendo:

Superclasse oi = new Subclasse();

Eu poderia acessar ele, por causa do acessador, né?
Teria como explicar o porquê do Polimorfismo nesse caso?

ups …é isso mesmo !!!

me desculpe e obrigado por me corrigir! :oops:

Sérgio.

Eu sempre tenho muito cuidado ao falar de reflexão.

E, eu estava sugerindo explicitamente que se violasse o encapsulamento usando reflexão justamente para se demonstrar como a herança de fato ocorreu, embora as regras de visibilidade restrinjam o acesso ao atributo. Somente através da reflexão (ou analisando o bytecode gerado, o que não é nada fácil) é possível demonstrar aspectos como esse.

Eu concordo com você que isso não é boa prova (nem sequer é prova), e que herança é uma regra. Mas você também restringiu herança a um aspecto de implementação, que se resume em “aumentar um escopo”. Herança certamente não é isso. Isso é uma consequência da herança, não o seu significado. A herança implementa a regra é um. Ou seja, semanticamente, um filho é um exemplo mais específico do pai.

Não é possível conceber essa regra tendo um filho que é “parte de um pai”, o que aconteceria se coisas não fossem herdadas. O filho pode não ter acesso ou controle sobre partes do pai, mas ele as possui.

[quote=ViniGodoy]
Eu concordo com você que isso não é boa prova (nem sequer é prova), e que herança é uma regra. Mas você também restringiu herança a um aspecto de implementação, que se resume em “aumentar um escopo”. Herança certamente não é isso. Isso é uma consequência da herança, não o seu significado. A herança implementa a regra é um. Ou seja, semanticamente, um filho é um exemplo mais específico do pai.

Não é possível conceber essa regra tendo um filho que é “parte de um pai”, o que aconteceria se coisas não fossem herdadas. O filho pode não ter acesso ou controle sobre partes do pai, mas ele as possui.[/quote]

O aumento do escopo não é um dado de implementação. É regra da linguagem. É graças a ele que pode ser feito shadowing. A implementação segue regras que têm que respeitar as regras da linguagem, mas como já disse, a JVM não força essas regras. Para outras linguagens, os compiladores podem estipular outras regras de escopo diferentes.

Herança não passa de um tipo especial de polimorfismo. Todo o polimorfismo é baseado em escopo. Herança , não é portanto diferente. As outras formas de polimorfismo adicionam capacidades paralelas enquanto herança cria uma hierarquia. É porque ele cria uma hierarquia que a condição é-um se aplica. Mas essa condição não define herança. O que define herança é apenas e só o aumento do escopo. Voce pode extender classes com outras que não “são um”. Isso não é sempre errado. Por exemplo, Stack extends Vector. Stack não é um vector, mas ele herda as mesmas operações. O conceito de herança como “é-um” é superficial e induz ao erro de pensar que é por isso que herança existe. Não é verdade.

O tem-um e é-um são formas de construir modelos de objetos. Sua implementação pode ser muito diferente conforme o paradigma que seguimos. Normalmente é-um pede herança, mas muitas vezes isso cria problemas (o famoso caso da pessoa fisica e juridica que herdam de pessoa. é-um parece ser a melhor forma de modelar, mas não é). A directiva tem-um pode ser implementa de várias formas desde um simples atributo até uma coleção com um unico elemento. As diretivas de modelagem têm formas padrão de se expressagem em java, e herança é a mais usada para é-um. Mas não tem sempre que ser assim.

Enfim, a directiva é-um é algo que existe em modelagem e que pode ser implementada com uso de herança, mas herança não foi criada apenas para expressar relações é-um. Ela foi criada para reaproveitar codigo numa forma hierarquica que se traduz por aumentar o escopo dos membros da classe a outra classes particular (a filha). O aumento do escopo é uma simples regra de visibilidade que o compilador força mas a JVM não controla.
Nem Herança nem o aumento do escopo são detalhes de implementação. Ou posto de outra forma: herança é o nome de uma forma especifica de aumento de escopo. Shadowing seria outra, por exemplo. O compilador entende essas regras e as força (compiladores diferentes, forçam regras diferentes).
A JVM apenas “dá-à-manivela” e faz tudo isso funcionar.

Já sei porque estamos discutindo. Porque existem várias definições de herança. E nenhuma delas é mais correta ou adequada, porque elas dependem da ótica e do problema sendo analisados. Resolvi procurar na internet e achamos a definição, clássica, o Booch, que é mais parecida com a minha. Por outro lado, a definição de LaLonde, é muito próxima da sua. Só para citar grandes nomes da OO.

Herança, pode ser encarada apenas do ponto de vista da análise, que está preocupada mais com a relação entre os tipos e com o significado dessa relação do que aspectos de implementação. O exemplo da PessoaFisica e PessoaJurica, mostra uma relação de duas classes parecidas, mas que na verdade são entidades distintas. Por isso, não deviam pertencer a mesma hierarquia, ou então, não num nível tão baixo.

Então, como aqui é o GUJ e é do Java que estamos falando, resolvi procurar a definição de herança segundo a Sun. Infelizmente, no site da Sun a definição é ambígua o suficiente para dar margem a discussão (a boa e velha “herança é quando um objeto herda de outro”):
http://java.sun.com/docs/books/tutorial/java/concepts/inheritance.html

Mas a definição de que herança é só uma forma de aumentar o escopo também é fraca. Você mesmo falou: “herança é o nome de uma forma especifica de aumento de escopo”. E o que torna essa forma específica? Justamente a criação de herarquias de classes. Qualquer hierarquia? Também não, classes friend (do C++), por exemplo, não formam herança e aumentam escopo. Classes onde se faz: class x : private Y, também não formam herança (formam relação “é implementado em termos de”) e também aumentam escopo.

Então, o que é específico nessa forma de aumento de escopo?

Simples… Cria uma classe com um atributo privato e tenta utilizar este atributo em outra classe que a herda. Resultado?

Erro de compilação!!!

Herança deveria ser estudada do ponto de vista da OO…senão amanhã aparece uma nova linguagem orientada a objetos e vão dar a sua própria definição de Herança? Estranho…

PQP… catzo.

Só para compreender essa m… toda que estão fazendo aqui.

Se eu tenho uma classe A e em baixo dela eu coloco um trangulo e outras classes abaixo desse triangulo (naquele diagrama de classe da UML que ninguém aqui sabe para que serve). Qual a idéia dessas classes?

Na idade da pedra da OO (Coad e Yourdon) chamavam isso de especialização, que era a forma de representar casos especiais ou de especializar uma superclasse. Como eu posso especilizar alguma coisa e ao mesmo tempo não ser essa coisa ou não ter partes dela.

Ou como eu posso passar no teste É UM se eu não tiver TODAS as características dessa coisa.

sinceramente senhores se a superclasse for constituída de um bit e eu criar uma subclasse que adicione outro bit, não importa a visibilidade do bit da superclasse, minha subclasse SEMPRE SERÁ (SER e NÃO TER) constituída por dois bits.

fw