Propriedade privada, herda ou não herda?

87 respostas
P

Opa,

pessoal, membros (atributos e metodos) privados sao herdados ou não? Pode parecer besta essa pergunta, mas olhando o livro da Kath vi q ela fala q nao eh herdado…e ao meu ver, herdar eh uma coisa, ter acesso é outra…

flw

87 Respostas

fec

Never!!!

LPJava

pardal to discutindo isso contigo desde de manha e tu sabe o q acho uhauhaua entao nao herda… um exemplo classico.

“seu pai tem uma cueca que é private, algo pessoal dele, vc nao vai querer herdar uma cueca dele ne? pq é algo pessoal e foi declardo como private.” Agora tu vai querer herdar a casa, o carro etc…
entao aquilo que é pessoal tu declara como private… :smiley:

flw"

saoj

Never, mas com umas sacanagens de reflection eu vejo ela… :slight_smile:

acopiara

Como saoj disse, via reflection dar para ler os atributos privados.

Dessa forma:

public class Aluno {
private String teste = "Feliz Natal";
}

import java.lang.reflect.Field;

public class AlunoMain extends Aluno {

	public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
		AlunoMain alunoMain = new AlunoMain();
		Field fields[] = alunoMain.getClass().getSuperclass().getDeclaredFields();
	    for (int i = 0; i < fields.length; i++){  
	       fields[i].setAccessible(true); 
	       System.out.println("Nome: "+fields[i].getName());
	       System.out.println("Valor: "+fields[i].get(alunoMain));
	    }
	}

}

[]'s

crpablo

“Membros marcados como privados não podem ser acessados por código em nenhuma outra classe que não aquela na qual o membro privado foi declarado.”

“Quando um membro é declarado como privado uma subclasse não pode herdar dele.”

Fonte: Certificação Sun para Programador Java? 5.

SCJP Exame 310-055

sergiotaborda

pardal_nb:
Opa,

pessoal, membros (atributos e metodos) privados sao herdados ou não? Pode parecer besta essa pergunta, mas olhando o livro da Kath vi q ela fala q nao eh herdado…e ao meu ver, herdar eh uma coisa, ter acesso é outra…

Não. São a mesma coisa.
Se algo não é herdado isso significa que não pertence ao escopo do objeto filho. Se não pertence ao escopo não ha como ter acesso. Se ele é private ele não pertence ao escopo do objeto filho, logo não tem acesso.

Reflection não vem ao caso porque o livro da Kathy não se mete por ai.

LPJava

crpablo:
“Membros marcados como privados não podem ser acessados por código em nenhuma outra classe que não aquela na qual o membro privado foi declarado.”

“Quando um membro é declarado como privado uma subclasse não pode herdar dele.”

Fonte: Certificação Sun para Programador Java? 5.

SCJP Exame 310-055

eu ja falei isso para ele, scanei a pag e envei mais ele nao acredita… ohh my god!

L

Cara, eu não me lembro onde, mas eu já li que os membros private são herdados, porém, não são acessados… só não lembro onde foi que eu li.

Andre_Brito

Foi mal chegar assim, mas se eu precisasse de um atributo que só as subclasses pudessem acessar, quem eu usaria? Protected ou public? Se eu usar publc ficaria uma variável global :S

P

foi aki:
http://ctp.di.fct.unl.pt/lei/lp1/teoricas/28.html

???

Andre_Brito

Mas e qual seria a vantagem de herdar e não acessar?

Continuo com a pergunta feita pela minha pessoa acima.

P

sabe o q eh HERANÇA ??

me fala o q é ?! :wink:

sergiotaborda

foi aki:
http://ctp.di.fct.unl.pt/lei/lp1/teoricas/28.html

Ai diz o seguinte :

É bem claro.

Essa é engraçada… herda mas não tem acesso…
a explicação é esta

Eles não seguem a mesma “visão” que as pessoas normais.

Dieval_Guizelini

Senhores,

1. herança sempre herda tudo (absolutamente tudo) da classe pai.
2. herança deve ser usado para "especializar" uma classe, ou seja, ampliar o escopo ou fazer algo para situações particulares.
Exemplo classico:

public Ponto { public double x,y; }
public Poligono {
   private Ponto[] pontos;
   public double perimetro() {
      double soma =0d;
      for( int i=1 ; i<pontos.length()~; i++) {
          soma += distancia(pontos[i],pontos[i-1]);
      }
   }
   abstract double area();
   public Ponto getPonto(int ponto) {
      if(ponto < pontos.length) return pontos[ponto];
      return null;
   }
   public void initPontos(int qtos) {
       pontos = new Ponto[qtos];
   }
   public double distancia(Ponto a, Ponto b) {
          return Math.sqrt( (a.x-b.x)*(a.x-b.x) + 
                                   (a.y-b.y)*(a.y-b.y) );
   }
   // outros métodos omitidos....
}

public class Quadrado extends Poligono {
    public Quadrao() {
        initPontos(4);
    }
    public double area() {
        double lado=distancia( getPonto(1), getPonto(0) );
        return lado*lado;
    }
}

observe que se o objetos da classe Quadrado não tivesse herdado os atributos e métodos, o seu funcionamento não seria o mesmo.

fw

Andre_Brito

Guizelini,

Eu também achava que heradava tudo… mas pelo que dizem estou errado.

Sim eu sei o que é HERANÇA!

Dieval_Guizelini

dedejava:
Guizelini,

Eu também achava que heradava tudo… mas pelo que dizem estou errado.

Sim eu sei o que é HERANÇA!

Então eu vou mudar a pergunta, você já viu ou alguém conseguiu te demonstrar que uma subclasse não herda todos os recursos (inclusive os privados)?

Tenho algumas propostas para avaliar a implementação do Java com relação a esse ponto:

A primeira:
Crie uma classe base com um tipo int como campo private e atribua a ele um inteiro qualquer.
Veja a quantidade de memória disponível
instancie e armazene em um array list 1000 desses objetos
Veja a quantidade de memória disponível
repita para 10.000 e 100.000.
Você conseguirá ver o quanto de memória esse objeto está ocupando.
Depois crie uma subclasse da primeira classe com mais um único atributo inteiro e faça o mesmo teste.
Qual será o resultado esperado? o dobro do consumo de memória.

A segunda:
Use o profile do netbenas e verifique os objetos.

A terceira:
faça a serialização de uma classe base e de uma subclasse, e armazene em disco.

eu dei uma procurada por cima na especificação da VM do java e não encontrei onde descreve isso, e deveria ser na parte de memória da VM. Mas o comportamento das linguagens como elas são implementadas internamente são muito similares. Lembrei de ter lido isso no manual do Delphi a alguns anos, procurei o manual no google e:

The internal data format of an object resembles that of a record. The fields of an
object are stored in order of declaration as a contiguous sequences of variables. Any
fields inherited from an ancestor class are stored before the new fields defined in the
descendant class.

fonte: Object Pascal Language Guide, 167
link: http://portal.aauj.edu/portal_resources/downloads/programming/delphi_object_pascal_language_guide.pdf

então quem te disse que uma subclasse não herda tudo da superclasse está definitivamente errado.

fw

P

Vejo que cada um fala uma coisa…

herda TUDO, nao herda PRIVATE…

afinal, HERDA ou NAO HERDA ???
:twisted:

:smiley:

LPJava

pardal_nb:
Vejo que cada um fala uma coisa…

herda TUDO, nao herda PRIVATE…

afinal, HERDA ou NAO HERDA ???
:twisted:

:smiley:

baseado na kathy ex-engenheira da sun, co-desenvolvedora do exame nao herda. e para com essa agonia pardal ja tem dois dias… uauauhauh

felipealbuquerque

Teste muito simples…

class A {
    private int i;
    short s;
}

class B extends A {
	
    void testeDeHeranca() {
        System.out.println(s);
        System.out.println(i); // não compila
        System.out.println(super.i); // não compila
    }
	
}

Como você pode ver, o atributo i não é herdado.
Membros privados de uma classe não são acessíveis por nenhuma outra. NENHUMA. As outras classes não sabem sequer se os membros privados existem.
Dada a afirmação acima, pense nisso: como uma classe pode herdar aquilo que ela nem sabe se existe?

OBS: Por membro, leia atributos e métodos.

ViniGodoy

Pessoal,

Existe uma diferença entre a existência de um atributo e a sua visibilidade.

O que o Dieval quer dizer é que, uma classe filha herdará um atributos e métodos do pai, no sentido de que, essas estruturas existirão, serão alocadas em memória, e serão usadas pelos mecanismos internos da classe. Afinal de contas, o filho é um objeto da classe pai e nada mais natural do que ele ter absolutamente todos os atributos do pai.

Entretanto, graças às regras de escopo, esses atributos e métodos não serão visíveis na classe filha. Daí a confusão. Assim, eles são herdados (pq existem e são acessados indiretamente pelos filhos), mas não são visíveis, estão fora do escopo da classe filha.

Por isso, não é possível fazer polimorfismo de métodos privados, por exemplo. O que ocorre se sobrescrevermos métodos privados é acabarmos com métodos de escopos diferentes. Um deles será usado quando a porção do pai invocar, outro será usado quando a porção do filho invocar que, se houvesse polimorfismo, apenas o método do filho seria invocado.

Isso é o que realmente acontece. Agora, a sensação para quem implementa um filho é de que os atributos e métodos privados não existem. Por isso tantos livros dizerem que não são herdados. Vai muito do que o autor considerar ou não herança.

Dieval_Guizelini

Com relação a kathy,

existem dois pontos, a forma com que ele escreve e para qual objetivo. Para o iniciante pode ser interessente ele ter a idéia de que não acontece a herança para entender o escopo de visualização, mas não a forma de implementação interna e quanto mais com relação a teoria de OO.

Outro ponto, você está se baseando em uma informação traduzida de má qualidade. Procure aqui mesmo no GUJ e você irá verificar que os tradutores fizeram um péssimo trabalho…

É como o Vini falou.

fw

Ps: felipealbuquerque recomendo que você veja o meu exemplo anterior, você está equivocado. O seu exemplo mostra o nível de controle sobre o escopo do recurso e não significa que a herança não ocorreu.

T

Não tem como Herdar membros privados… por isso tem os Gets e Setters!

Abraços!

Dieval_Guizelini

truck1n:
Dieval Guizelini:

  1. herança sempre herda tudo (absolutamente tudo) da classe pai.

Não tem como Herdar membros privados… por isso tem os Gets e Setters!

Abraços!

Vocês estão andando em circulos…

os métodos são apenas “interfaces” entre os estados internos de um objeto (propriedades, variáveis de instâncias, tipos primitivos) e o mundo externo (outros objetos). Os métodos por si só não são capazes de PRESERVAR a informação.
Quando se cria uma instância de uma subclasse ela possui TODAS as características da classe pai, por isso ela pode ser comparada com o operador instanceof da classe pai e ter como resultado verdadeiro, pois este operador verifica que objeto (de uma subclasse) É uma instância da classe pai, o que é muito diferente de TER um membro de uma determinada classe.

Logo o fato de um ou mais recursos serem declarados como private não impede destes mesmos recursos estarem presentes (fazerem parte) das instâncias de classes filhas. Não está em discussão se estes recursos são ou não acessíveis através destas instâncias e apenas se eles são ou não HERDADOS.

fw

Andre_Brito

truck1n:
Dieval Guizelini:

  1. herança sempre herda tudo (absolutamente tudo) da classe pai.

Não tem como Herdar membros privados… por isso tem os Gets e Setters!

Abraços!

ACHO que você tem razão… Me deixou na dúvida agora… se eu tenho uma variável de instância j private, usar um getJ e um setJ(tipo novoJ), eu posso acessar com o get e setar com o set? Então ela é tanto visível quanto pode ser modificada e manipulada, concorda?

Dieval_Guizelini

dedejava,

em partes,

você deve lembrar que os métodos podem realizar validações, e eventualmente não modificar o conteúdo da variável. Exemplo o CPF, você pode ter um método setCPF que valide a informação passada e se ela não passar pelo algoritmo de validação ela não será atribuída a propriedade cpf.
Na prática, os set e gets são recomendados principalmente para quando você precisar incluir alguma validação ou gerar um “evento/notificação” de modificação ou de acesso possa ser implementado a posteriori. Ou por exemplo, para se modificar o domínio ou realizar qualquer modificação interna no objeto sem a necessidade de reescrever todos as classes e objetos que façam uso destes recursos.
O legal de se compreender as definições de OO, é que se bem utilizados os métodos como interfaces das propriedades, você poderá modificar com relativa segurança quase tudo do seu objeto sem impactar nos outros pontos do sistema. O outro ponto é que a propriedade pode ser relevante para outros valores/estados do próprio objeto.

fw

Andre_Brito

Eu fiz os seguintes códigos:

/**
 * Write a description of class Superclasse here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Superclasse
{
    // instance variables - replace the example below with your own
    private int naoHerda;
    int herda;

    /**
     * Constructor for objects of class Superclasse
     */
    public Superclasse()
    {
        naoHerda = 20;
        herda = 10;
    }
    
    /**
     * Metodo acessador ao naoHerda
     */
    public int getNaoHerda() {
        return naoHerda;
    }
    
    /**
     * Metodo acessador ao herda
     */
    public int getHerda() {
        return herda;
    }
    
    /**
     * Metodo modificador de naoHerda
     * @param novoNaoHerda Novo valor de naoHerda
     */
    public void setNaoHerda(int novoNaoHerda) {
        naoHerda = novoNaoHerda;
    }
    
    /**
     * Metodo modificador de herda
     * @param novoHerda Novo valor de herda
     */
    public void setHerda(int novoHerda) {
        herda = novoHerda;
    }
}

A a subclasse

/**
 * Write a description of class Subclasse here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Subclasse extends Superclasse
{
    /**
     * Constructor for objects of class Subclasse
     */
    public Subclasse()
    {
        super();
    }
    
    /**
     * Vai apresentar os valores 10 e 20 na tela
     */
    public void imprimeTodos() {
        System.out.println("super.herda = " + super.herda);
        System.out.println("herda =  " + herda);
        //System.out.println("super.naoHerda = " + super.naoHerda); // esse nao compilou, como o felipao disse
        //System.out.println("naoHerda = " + naoHerda); // esse tambem nao
        System.out.println("nao herda = " + super.getNaoHerda());
    }
    
    /**
     * Vai mudar os valores de herda e naoHerda (pelo menos vai tentar)
     */
    public void setValores(int novoNaoHerda, int novoHerda) {
        super.setNaoHerda(novoNaoHerda);    // aqui ele compila em ambos... mesmo sendo private, e possivel mudar o valor da variavel entao?
        super.setHerda(novoHerda);
    }
}

Bom… aí já tá dito né… agora é possível tanto acessar os valores e mostrar os mesmos e setar novos valores pra eles.
Tá certo e coeso isso?

M

Senhores,
Para responder é necessário tão somente lembrar das definições em OO para Herança:
Por herança compreendemos todos ser a capacidade que uma determinada classe possui de encapsular os membros de uma outra classe, então chamada “superclasse”. Sabemos ainda que uma relação de herança corresponde a uma relação “is a”. Ou seja: se “uma classe” “estende” uma outra, ela é “uma outra”. Se é “uma outra”, possui todos os membrpos existentes em “uma outra”, o que inclui os membros privados. Pronto! A questão está respondida!
Mas, para que não hajam dúvidas, lembremos a definição de membro privado. Que diz que um membro privado só pode ser acessado a partir da classe em que é encapsulado. Desta forma, mesmo que “uma classe” herde um membro privado de “uma outra”, não poderá acessá-lo pois este membro não foi encapsulado em "uma classe’, mas sim em “uma outra”. Caso seja necessário op acesso a estes membros privados em “uma outra” a partir de “uma classe”, definem-se seletores e modificadores públicos para estes membros em “uma outra”.

felipealbuquerque

Eu li os posts desse tópico, que é muito interessante, e estou convencido de que membros privados de superclasses são herdados pelas suas subclasses. Já a visibilidade é outra coisa, eu estava confundindo herança com visibilidade.

Obrigado a todos pelas informações fornecidas!

LPJava

certo… visibilidade é outra coisa… mais segundo a kathy o membro nao é herdado… seu filho tem o mesmo cpf que vc?
se tem um campo de cadatro cpf vc vai querer colocar private nao? para que outras classes nao acesse… o membro…

veja em anexo o que kathy diz…


felipealbuquerque

Uma classe A herdar de uma classe B não significa que um objeto da classe A herde de outro da classe B.
O exemplo do CPF ilustra bem essa afirmação. O pai é um objeto da A e tem um atributo privado cpf. O filho é da classe B, que estende A, portanto também tem um cpf. Não necessariamente os CPFs são os mesmos. Mas o fato é que os dois têm um CPF.
Mas… como o CPF é privado, o filho não consegue acessá-lo ao menos que haja métodos getters e setters para esse atributo, acessíveis para a classe B, definidos na superclasse. Havendo esses métodos, a edição e a obtenção desse atributo ocorrem sem problemas.

Exemplo em código:

class A {
    private String cpf;

    public String getCpf() {
        return this.cpf;
    }

    public void setCpf(String cpf) {
        this.cpf = cpf;
    }
}

class B extends A {
    //
}

class Teste {
    
    public static void main(String[] args) {
        B b = new B();
        b.setCpf("99.999.999-99"); // Alterando a propriedade CPF
        System.out.println(b.getCpf()); // Obtendo a propriedade CPF
    }

}

Como podemos ver, o atributo é herdado, tanto que conseguimos acessá-lo através de métodos getters e setters. O que não podemos fazer é acessar o atributo cpf diretamente, pois não há privilégios de visibilidade suficientes para tal ação.

Espero ter conseguido expor corretamente o meu ponto de vista. :smiley:

A propósito… feliz natal (antecipado) a todos!

M

Caro Irmão,
Não compreendi o lance de “ter o mesmo CPF do meu pai”. A comparação não é o que se pode chamar de acertada!
Em princípio eu e meu pai não poderíamos ser de classes distintas a não ser que eu fosse algo que meu pai não é (ambos somos apenas pessoas) e não se herda valores, como o numero do CPF, mas sim atributos como ter ou não ter CPF.
Disse e torno a repetir: o fato de um membro não estar disponível não significa que o mesmo não exista. O autor do livro cometeu um pequeno engano tentando “simplificar” a coisa. Ao menos em níve de código a coisa é diferente!
Depois, quando tiver tempo, eu vou postar um código que usa reflexão (introspecção) para provar via código o que digo!
Aproveito o ensejo para desejar um Feliz e Consciencioso Natal (Kristnasko) e um 2008 de realizações!
Shalom!
San

felipealbuquerque

Realmente esse exemplo de CPF de pai e filho dado pelo nosso amigo não foi muito legal. Mas serviu para que eu pudesse montar um exemplo… hehe.

Na verdade, um pai TEM-UM filho (ou mais).

LPJava

felipealbuquerque:
Uma classe A herdar de uma classe B não significa que um objeto da classe A herde de outro da classe B.
O exemplo do CPF ilustra bem essa afirmação. O pai é um objeto da A e tem um atributo privado cpf. O filho é da classe B, que estende A, portanto também tem um cpf. Não necessariamente os CPFs são os mesmos. Mas o fato é que os dois têm um CPF.
Mas… como o CPF é privado, o filho não consegue acessá-lo ao menos que haja métodos getters e setters para esse atributo, acessíveis para a classe B, definidos na superclasse. Havendo esses métodos, a edição e a obtenção desse atributo ocorrem sem problemas.

Exemplo em código:

class A {
    private String cpf;

    public String getCpf() {
        return this.cpf;
    }

    public void setCpf(String cpf) {
        this.cpf = cpf;
    }
}

class B extends A {
    //
}

class Teste {
    
    public static void main(String[] args) {
        B b = new B();
        b.setCpf("99.999.999-99"); // Alterando a propriedade CPF
        System.out.println(b.getCpf()); // Obtendo a propriedade CPF
    }

}

Como podemos ver, o atributo é herdado, tanto que conseguimos acessá-lo através de métodos getters e setters. O que não podemos fazer é acessar o atributo cpf diretamente, pois não há privilégios de visibilidade suficientes para tal ação.

Espero ter conseguido expor corretamente o meu ponto de vista. :smiley:

A propósito… feliz natal (antecipado) a todos!

cara vc foi infeliz nesse exemplo, pq o fato de vc chamar um metodo e ele chamar uma variavel privada nao quer dizer que a sublclasse obteve a variavel… o que vc fez apenas foi chamar um metodo… e ele fez a tarefa que tem q realziar… se chamou uma variavel private, ou se mudou o valor de um variavel isso nao importa para a subclasse, sao coisas distintas velho… primeiro temos que aprender o conceito de “herdar”… e esse seu exemplo nao mostra isso com a variavel private… alias lembra de uma das regras do encapsulamento e de usar os metodos set e get como nomeclatura javabeans?

Bom sugiro fortemente dar uma lida no livro da kathy sobre o assunto capitulo 2… e na minha opniao… acho que aqui no forum, em termo academico e de experiencia profissional, nao tem no forum, profissionais com o nivel superior que o da kathy sierra para discutir que a afirmação dela está errada. Levando em conta q ela viveu dentro da sun por mais de 10 anos… e participou de todos os projetos envolvendo java…

flw!! feliz natal!

Andre_Brito

LPJava,

Sobre o CPF, você me deixou um pouco na dúvida. Seria privado (como o nome, data de nascimento, e tal), mas não seria característica própria de cada objeto? A classe só ditaria o campo, não teria um cpf int = 2222222;. Porque na verdade, TODOS tem CPF, data de nascimento, nome e tal. Desculpe se falei algo de errado, mas esse assunto é MUITO ambíguo.

Abraço LPJava e os demais e feliz natal.

LPJava

dedejava:
LPJava,

Sobre o CPF, você me deixou um pouco na dúvida. Seria privado (como o nome, data de nascimento, e tal), mas não seria característica própria de cada objeto? A classe só ditaria o campo, não teria um cpf int = 2222222;. Porque na verdade, TODOS tem CPF, data de nascimento, nome e tal. Desculpe se falei algo de errado, mas esse assunto é MUITO ambíguo.

Abraço LPJava e os demais e feliz natal.

no caso do exemplo do cpf, o que foi herdado foi apenas o metodo… faz o teste de colocar o metodo setCPF como private para vc ver… entao… todo mundo tem um cpf… mais nesse caso ai… o cpf nao foi herdado por ser private… e como coloquei na pagina anterior uma parte que a kathy fala no livro… dela… exatamente esse assunto e explica pq nao herdado… o q acontece no exemplo dado, é uma caracteristica de encapsulamento e nao de herança…

para comprovar o que to falando so muda o metodo de public para private para vc ver… que cpf nao foi herdado.

uma pergunta: seu pai herdou a cueca do seu avo? ou ele herdou apenas o que foi definido pelo seu avo?
pense nisso, pois é a mesma coisa dos membros private.

flw! :smiley:

Andre_Brito

Heheh. Pois é.
A subclasse não herda visivilmente, mas veja que no meu exemplo que eu dei na página anterior o campo é herdado, posso mudar ele com métodos modificadores (mutators, como diz Deitel) e acessar o valor das mesmas com gets. Por que isso ocorre?

Meu pai não herda a cueca do meu avo (que poderia ser verde, rasgada e de tamanho x), mas herda o ter que usar a cueca (que pode ser de um tipo diferente, tipo box :p).

Abraço.

LPJava

dedejava:
Heheh. Pois é.
A subclasse não herda visivilmente, mas veja que no meu exemplo que eu dei na página anterior o campo é herdado, posso mudar ele com métodos modificadores (mutators, como diz Deitel) e acessar o valor das mesmas com gets. Por que isso ocorre?

Meu pai não herda a cueca do meu avo (que poderia ser verde, rasgada e de tamanho x), mas herda o ter que usar a cueca (que pode ser de um tipo diferente, tipo box :p).

Abraço.

uhaua rpz eu desistir de explicar esse assunto eu fiquei uma manha com pardal discutindo isso hhee… mas o procedimento do metodo é diferente cara… muito diferente… é uma pratica de encapsulamento que é diferente a herança… lembra da regra de coesao e acomplamento? os dois envolve herança e encapsulamento… :D.

obs.: Eu sei pq fizeram confusao com algo simples e visivel… e se der uma lida nos conceitos de OO vai ver que a kathy está correta… e a galera ainda permanece dizendo que herda meu deus… uhauha

flw!

ViniGodoy

LPJava:
certo… visibilidade é outra coisa… mais segundo a kathy o membro nao é herdado… seu filho tem o mesmo cpf que vc?
se tem um campo de cadatro cpf vc vai querer colocar private nao? para que outras classes nao acesse… o membro…
veja em anexo o que kathy diz…

O exemplo do CPF foi péssimo. Isso é o valor de um dado, de uma instância. Você e o seu filho tem um CPF e ambos os CPFs significam a mesma coisa. Isso, é a herança. A classe está relacionada a definição do atributo, não ao seu valor.

A Kathy comete um erro comum, que é justificável pelo papel que se propõe: Trocar precisão técnica por didática. É mais fácil explicar para um aluno que um atributo não é herdado. O aluno, no estágio inicial, ainda não está familiarizado com o conceito da herança e não está também muito seguro das regras de escopo e visibilidade. Ele pode começar a trabalhar esses conceitos e, mais tarde, quando tiver amadurecido, você explica o conceito com mais precisão.

Na matemática, fazemos isso desde o jardim. Na física também funciona assim. A medida que os conjuntos numéricos crescem, que as definições se aprofundam, começamos a entender mais detalhes.

Em suma, revisamos definições que são mais imprecisas, mas suficientes para nosso conhecimento na época, e as substituimos por outras mais precisas e adequadas ao nosso conhecimento atual.

P

ViniGodoy,
segundo a Kathy: métodos privados não são herdados. Portanto, em uma herança, se uma subclasse criar um metodo com mesma assinatura do metodo contido na classe pai (porem com acesso PRIVATE), vc não está sobrescrevendo NADA, já que a subclasse desconhece tal metodo na classe pai…

acho meio estranho ela cometer 2 erros “grosseiros” em um mesmo capitulo …

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. 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).

P

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 ?

:?

jgbt

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

sergiotaborda

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.

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).

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.

P

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 …

P

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.

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?! :?

P

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 !

Andre_Brito

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.

P

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 !

P

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

H

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…

Andre_Brito

pm:
dedejava:

Não herdam explicitamente, mas com métodos set e get posso acessá-los tranquilamente.

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

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?

P

ups …é isso mesmo !!!

me desculpe e obrigado por me corrigir! :oops:

ViniGodoy

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.

sergiotaborda

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.

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.

ViniGodoy

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?

falvesti

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

Erro de compilação!!!

felipeguerra

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…

Dieval_Guizelini

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

Kassiane_Pretti

Pessoal esse tópico tá rendendo heim…
E vcs falam, falam e não saem do lugar. Arrumaram diversas maneiras
de dizer a msm coisa.

Na minha humilde opinião e através de tudo que foi dito pude concluir que todas as variáveis e metodos são herdados de
uma classe, mas as variaveis “private” não são acessiveis diretamente, mas somente pelos metodos set e get. Então se uma determinada variavel
não pode ser acessada e modificada por uma outra classe no caso da
herança devemos repensar o encapsulamento da variavel.

Seria isso q eu penso :oops:

dicabeca

qualquer coisa private nao herda,sendo variavel ou metodo,se quiserem modificar uma variavel private,crie um metodo publico,logico o metodo na classe pai onde c encontar a variavel vlw!!!

S

num herda naum,…

P

Logico que herda…pq vcs não fazem o download do BlueJ ou olhem do debug de qq IDE que o atributo privado do pai pertence ao filho, isto é, foi herdado.

Herança é diferente de visibilidade(acesso)

pq esta tão dificil de entender ?

Segue os prints para os mais preguiçosos

P

Olhem o atributo “nome”…

sergiotaborda

Estamos conversando :wink:


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?

Só ha uma hierarquia em java.
Então, herança é apenas uma forma de aumentar o escopro do membros de uma classe que implicam que a classe derivada pertence na hirarquia da original.

O que vc está dizendo aqui é que existem outras formas de aumentar o escopo, que não são a herança. Certo. Como eu disse: em java, shadowing também é uma forma de aumentar o escopo.
Por existirem várias formas de aumentar o escopo ( static seria outra) é que eu disse que a herança é uma forma especifica. É uma entre outras.

F

na minha opinião não herda.
Pode ocorrer coisas estranhas como o reflections
um método publico chamar um privado e assim ter um pseudo acesso, mas isso não é a definição.
É como herança múltipla, não tem, mas vc pode contornar.

Dieval_Guizelini

Eu estou ficando realmente surpreso com a profundidade da capacidade lógica de pensar…

Se for considerada uma classe pai que tenha uma propriedade com o modificador de acesso private e um método que lê essa propriedade, quando eu estender essa classe e fizer o uso desse método herdado, a propriedade que preserva a informação (declarada na classe pai como private) estará alocada na memória do além e naturalmente não fará parte do objeto que é uma instância da classe filha e quando um objeto dessa subclasse fizer uma leitura através desse método get, a VM do java irá romper a barreira do material e obter uma informação do além e que naturalmente NÃO FARÁ PARTE DO OBJETÖ…

Vamos continuar a conversar sobre a policromia dos cristais partidos, mesmo com quem entra, não lê os posts anteriores e repete hipoteses já derrubadas e não fundamentadas…

vw :twisted:

paulovittor23

Interessante… pensando que, todo filho é o pai de uma forma especializada logicamente a resposta teria de ser sim… acredito que as referências que dizem que não herda seja pra facilitar o entendimento do modificador de acesso apenas, não levando em conta a essencia da coisa…

F

Vc consegue chamar o método, mas a definição é que não herda.

public class SuperPrivate { public static void main(String args[]){ Filha a = new Filha(); a.acessaMetodoPrivado(); } } class SuperClass{ public void metodoPublico(String arg){ metodoPrivado(arg); } private void metodoPrivado(String arg){ System.out.println("Método privado chamado arg='"+arg+"'"); } } class Filha extends SuperClass{ public void acessaMetodoPrivado(){ super.metodoPublico("teste"); } }
Por exemplo, vc herda o monitor da pessoa?
Não, porém vc consegue modificar o que é desenhado nele…

sergiotaborda

Dieval Guizelini:
Se for considerada uma classe pai que tenha uma propriedade com o modificador de acesso private e um método que lê essa propriedade, quando eu estender essa classe e fizer o uso desse método herdado, a propriedade que preserva a informação (declarada na classe pai como private) estará alocada na memória

Memoria = JVM = Plataforma = Implementação
Herança = Regra = Linguagem = Teoria

Linguagem é diferente de plataforma. O que acontece na memoria não tem nada a ver com a linguagem.
A prova disso é que muitas linguagens compilam o mesmo bytecode e funcionam na mesma JVM usando a mesma memoria. É dificil de aceitar isto ? Acho que não.

Dado que o que acontece na memoria é completamente inutil para saber se ha herança ou não , porque perder tempo com esse exemplo ?

O livros não afirmam que membros privados não são herados simplesmente porque querem se didáticos, eles dizem isso porque é a verdade. A prova é que dada uma classe que extende outra vc não consegue acessar nenhum dos membros privados da classe hierarquicamente superior.

Se vc acessa um método publico i ou protegido da classe pa que por sua vez acessa a variável privada , tudo bem. Isso não prova que a clase filha tem acesso à variável privada.

Dieval_Guizelini

Memoria = JVM = Plataforma = Implementação
Herança = Regra = Linguagem = Teoria

Linguagem é diferente de plataforma. O que acontece na memoria não tem nada a ver com a linguagem.
A prova disso é que muitas linguagens compilam o mesmo bytecode e funcionam na mesma JVM usando a mesma memoria. É dificil de aceitar isto ? Acho que não.

Depende, em que você queira aplicar, quando falamos em Java, normalmente estamos falando do conjunto todo.
Com relação a sua definição: “Herança = Regra = Linguagem = Teoria”, poderia ser melhor definida que “Herança é conceito definido na OO” e a interpretação dos engenheiros da SUN com relação a este conceito é exclusivamente implementado com o uso da palavra chave extends, e conforme as especificações do JCP para as VM.

Infelizmente não posso concordar, apenas com um conhecimento de como a ferramenta manipula a memória, IO e etc, pode-se compreender vários conceitos. Apenas para citar, que é outro ponto polêmico no Java, a passagem de parâmetros por valor ou referência.

sergiotaborda:

O livros não afirmam que membros privados não são herados simplesmente porque querem se didáticos, eles dizem isso porque é a verdade. A prova é que dada uma classe que extende outra vc não consegue acessar nenhum dos membros privados da classe hierarquicamente superior.

Se vc acessa um método publico i ou protegido da classe pa que por sua vez acessa a variável privada , tudo bem. Isso não prova que a clase filha tem acesso à variável privada.

Como docente não posso “desconsiderar” a literatura normalmente aceita pela sociedade, mas como pesquisador da área de desenvolvimento eu posso afirmar dois grandes problemas com a literatura técnica, principalmente na área da informática:

  1. Os tradutores normalmente não possuem conhecimento da área de informática, e quando possuem são fracos. O maior exemplo desse problema, talvez seja o livro de Inteligência Artificial do Norvig e Russellque quase conseguiu acabar com a área de IA no Brasil no fim da década de 80 e início dos anos 90.
  2. O conceito de “aspectos didáticos” associados aos livros que se destinam a treinamentos ou preparação para certificações são em sua maioria ruins e apresentam metodologias que já não são mais tão utilizadas no sistema educacional do Brasil. Principalmente as metodologias baseadas em Piaget. A exemplo o livro da Kathy.

Agora, focando no conceito de OO, de herança, observe que quando uma subclasse executar qualquer código que faça uso (ou é dependente) de uma propriedade declarada com private, ela não deveria funcionar se não tivesse herdado essa característica. Logo, volto a afirmar que toda classe especializada de outra classe através do recurso de herança, seja em Java ou em qualquer linguagem do paradgima Orientado a Objetos, terá todos os recursos da classe pai.

fw

francislon


ViniGodoy wrote
Existe uma diferença entre a existência de um atributo e a sua visibilidade.

O que o Dieval quer dizer é que, uma classe filha herdará um atributos e métodos do pai, no sentido de que, essas estruturas existirão, serão alocadas em memória, e serão usadas pelos mecanismos internos da classe. Afinal de contas, o filho é um objeto da classe pai e nada mais natural do que ele ter absolutamente todos os atributos do pai.

Entretanto, graças às regras de escopo, esses atributos e métodos não serão visíveis na classe filha. Daí a confusão. Assim, eles são herdados (pq existem e são acessados indiretamente pelos filhos), mas não são visíveis, estão fora do escopo da classe filha.

Por isso, não é possível fazer polimorfismo de métodos privados, por exemplo. O que ocorre se sobrescrevermos métodos privados é acabarmos com métodos de escopos diferentes. Um deles será usado quando a porção do pai invocar, outro será usado quando a porção do filho invocar que, se houvesse polimorfismo, apenas o método do filho seria invocado.

Pra mim ViniGodoy foi muito feliz nessa resposta, o fato de não ser visivel naum quer dizer que não foi herdado.
Tá tudo explicado ai :slight_smile:

Zeed01

Boa tarde colegas !

Nem vou dar minha humilde opinião no meio de tantos pensadores e filósofos !

Mas juro que gostaria de saber o que a Kathy diria sobre essa frase:

"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. "

:smiley:

[]s

P

Uau… :shock:

Quando criei este post não pensei q daria tanta repercussão…

Quando eu acho q já formei a minha opinião sobre o assunto, vem um post e muda tudo… :?

(por eqt estou do lado que não herda - JVM, acessa. E, se analisar pelo conceito de OO herda.

Zeed01

Boa tarde colegas !

Hahahahahaha !!!

Eu quero a cueca do meu pai !

Essa foi a melhor de todas !

[]s

sergiotaborda

Você defende, portanto, que o que está em memoria reflete sem equivocos as regras da linaguem java ?
Vc não está pensando no problema como um todo.

Vc diz que se a classe A tem o atributo z então B que estende A também tem. A sua justificativa é que no debug (que é feito por uma ferramenta de runtime ) z aparece num objecto do tipo B.

Se A também tiver um atributo y estático ele também irá aparece em cada objecto de B. Contudo , isto não significa que y existe em cada objecto de B. Como pode um atributo (um só) pertencer simultaneamente a N objetos diferentes ?

A resposta é simples. A ferramente de debug mostra o estado do objeto, mas isso não significa que ela é limitada pelos atributos do objeto. Ela mostra tudo o que existir. Independentemente de onde.

Por outro lado , quando diz que z existe em B isso não é verdadeiro. z existe em A e B é uma expanção de A.
É como fazer um circulo à volta da são paulo e dizer que são paulo pertence ao circulo. Mas se eu fizer um circulo maior em torno do primeiro, são paulo continua petencendo ao circulo menor. Ele apenas está dentro do maior, porque este contém o menor. Estar “incluso” é diferente de “existir em”

Se aceitarmos o argumento de que z existe em B porque existe em A, porque a ferramente assim mostra, temos que aceitar que y existe em cada objecto do tipo de B, porque a ferramenta assim mostra. E isso é um absurdo porque y é estático (ele não pertence aos objetos). Logo, não podemos aceitar o argumento baseado em ferramentas de debug.

Os implementadores da ferramenta de debug poderiam ter escolhido esconder coisas estáticas. Seria mais correto do ponto de vista teorico, mas seria absurdo do ponto de vista prático. Por isso que qualquer coisas que seja uma ferramenta , ou uma API que se baseia no estado da memoria em runtime não pode ser argumento para provar o que é regra em tempo de compilação. O fato de membros privados não serem visiveis em tempo de compilação é que é a regra. E isso que significa “membros privados não são herados” ou seja, “a visibilidade de membros privados não se estende a subclasses”. Privados = “só dela”.

Gauss

Herda mas n eh possivel ter acesso.

O objeto n passa de uma referencia na memoria, portanto é herdado.

E isso nao vai levar em lugar algum.

S

sergiotaborda:
Dieval Guizelini:
Se for considerada uma classe pai que tenha uma propriedade com o modificador de acesso private e um método que lê essa propriedade, quando eu estender essa classe e fizer o uso desse método herdado, a propriedade que preserva a informação (declarada na classe pai como private) estará alocada na memória

Memoria = JVM = Plataforma = Implementação
Herança = Regra = Linguagem = Teoria

Linguagem é diferente de plataforma. O que acontece na memoria não tem nada a ver com a linguagem.
A prova disso é que muitas linguagens compilam o mesmo bytecode e funcionam na mesma JVM usando a mesma memoria. É dificil de aceitar isto ? Acho que não.

Dado que o que acontece na memoria é completamente inutil para saber se ha herança ou não , porque perder tempo com esse exemplo ?

O livros não afirmam que membros privados não são herados simplesmente porque querem se didáticos, eles dizem isso porque é a verdade. A prova é que dada uma classe que extende outra vc não consegue acessar nenhum dos membros privados da classe hierarquicamente superior.

Se vc acessa um método publico i ou protegido da classe pa que por sua vez acessa a variável privada , tudo bem. Isso não prova que a clase filha tem acesso à variável privada.

Eu concordo plenamente com você. Detalhes de implementação da linguagem não nos interessa e até podem mudar entre versões, sem impactar na linguagem.
Um outro exemplo é o compartilhamento de métodos pelos objetos da mesma classe.

Dieval_Guizelini

Eu não disse que a herança é justificada pela representação da informação que o debug mostra e sim pelo fato que de a classe B ao estender A, ela terá todos os recursos (propriedades e métodos) independentes da visibilidade dos mesmos.

Eu acredito que esse é o ponto principal da questão e onde surge a divergência de opniões, o fato de um círculo ter outro não significa que É o mesmo.
O problema não está no fato de eu ter duas classes que TENHAM propriedades iguais, exemplo:

public class A { public int a; } public class B { public int a; }
Neste caso, não existe nenhuma relação entre estas classes, são classes distintas. Mas que possuem (usando o seu termo, contém) uma propriedade do mesmo tipo de informação e com o mesmo identificador. Mas não são a mesma coisa, logo:

B b = new B(); System.out.println( b instanceof A); // sempre será falso
Agora, quando temos:

public class A { modificador_qualquer int a; } public class B extends A { }
independentemente do modificador, sempre as instâncias de B produzirão verdadeiro no teste abaixo:

B b = new B(); System.out.println( b instanceof B); // sempre será falso
E este é ponto para mim, ou seja, ter uma classe herdada de outra em java, implica que:

  1. ela sempre passará no teste É UM;
  2. ela sempre terá os recursos da classe pai, independentemente de visibilidade e da disponibilidade desse recursos para a própria subclasse ou classes terceiras.

Observe novamente que herança não está associada a idéia de pertinência ou de conter.

Novamente o seu exemplo deixa claro que você está misturando o conceito de pertinência com o conceito de existência.
quando um recurso é declarado como static, esse recurso pertence a classe e está associado a todos os objetos dessa classe. Se eu criar uma subclasse, essa subclasse será também associada ao mesmo recurso. Na prática, estamos falando de uma única região de memória compartilhado por todos os objetos.

Então, para você a herança é uma regra implementada na etapa de compilação? Os objetos existem na fase de compilação?
As regras de visibilidade são validadas também em tempo de compilação, mas não somente nesta etapa. A herança e sua implementação é uma definida no nível de classe, mas as conseqüências, ou sua real implementação ocorre em tempo de execução tanto no nível de classe como de objeto.
Enquanto o código não estiver em execução, a memória não será alocada, a classe não receberá os recursos da classe pai e assim por diante.

fw

Dieval_Guizelini

Schuenemann:
[…]
Eu concordo plenamente com você. Detalhes de implementação da linguagem não nos interessa e até podem mudar entre versões, sem impactar na linguagem.
Um outro exemplo é o compartilhamento de métodos pelos objetos da mesma classe.

E segundo o seu exemplo, o java poderia deixar de separar a memória em heap e stack e considerar tudo pertencente ao heap ou ao stack (implementando-os conforme as regras padrões de compiladores) e continuariamos a ter o mesmo funcionamento na passagem de parâmetros e etc.

Da mesma forma ele poderia mudar a quantidade de bytes de seus tipos primitivos, digamos que um int passa de 4 para 8 bytes, e como não é necessário conhecer a implementação eu não terei nenhuma conseqüência para as minhas aplicações, para os estudos de viabilidade, etc

Com relação a sua opnião da relevância da forma que uma linguagem implementa determinados recursos, vamos esperar um pouco e ver o quanto tempo ela dura. É a mesma coisa de dizer que todos os sistemas de arquivos são iguais e podem ser usados para qualquer solução em qualquer situação, ou que não importa como os SO são implementados…

Com relação aos métodos compartilhados, é também um padrão de implementação de compiladores, poderiamos citar aqui as DLL, os códigos nativos, os recursos de JNDI e etc, mas nada disso teria relevância para os dois conceitos em discusão, que são: herança e visibilidade dos recursos.

fw

Kassiane_Pretti

Eu acho que vcs estão com tanta dúvida pois estão confundindo herança com visibilidade. Temos que definir as duas coisas separadamente para entender melhor a questão das variaveis privadas.
Na verdade elas são herdadas, mas não serão visiveis ao menos se utilizarmos os métodos publics set e get delas.

cv1

Caralho, voces tao discutindo isso AINDA!?

sergiotaborda

Dieval Guizelini:
sergiotaborda:

Vc diz que se a classe A tem o atributo z então B que estende A também tem. A sua justificativa é que no debug (que é feito por uma ferramenta de runtime ) z aparece num objecto do tipo B.

Se A também tiver um atributo y estático ele também irá aparece em cada objecto de B. Contudo , isto não significa que y existe em cada objecto de B. Como pode um atributo (um só) pertencer simultaneamente a N objetos diferentes ?


Eu não disse que a herança é justificada pela representação da informação que o debug mostra e sim pelo fato que de a classe B ao estender A, ela terá todos os recursos (propriedades e métodos) independentes da visibilidade dos mesmos.

Mas como vc prova que tem ? Esse é o ponto.
Várias pessoas apresentam a prova usando mecanismos de debug, uso de memória, profilers, etc… ou seja, ferramentas de runtime que interagem com a JVM.

Acho que ficou claro que esse tipo de ferramentas não pode provar coisa alguma sobre a estrutura dos objetos em memoria. Elas mostram aquilo para que foram criadas e não a estrutura real na memoria.

1)Para que se aceite que B tem todos os recursos de A é necessário provar isso. Sendo que o uso de ferramentas não prova isso, não se pode (agora/ainda) aceitar que B tem todos os recursos de A.

2)Mesmo aceitando que B tem os recursos de A isso não acontece porque A é copiando para B e acrecentado de mais coisas. Acontece porque B é A. Sendo assim, tudo aquilo que é de A é de B. Tudo, exceto o que é apenas de A, obvio.

Objectos do tipo B sempre são objetos do tipo A. Aqui não ha dúvidas. Isso é herança: construir tipos a partir de outros. O ponto em causa é são os membros privados de A.

Não, não terá. E é isso que tem que ser provado.
Entende que se eu declaro algo private em A e isso existe em B então não é mais private em A; Não é mais interno a A, é agora compatilhado com B. A noção que algo privado pertence a algo mais que o seu proprio dono é absurda. Ela fere o conceito de encapsulamento que é o conceito mater em OO. As coisas são feitas privadas exactamente para que não existam em outros lugaes.

Mas o que significa “existir” em OO. Nada.
As coisas não “existem” elas são definidas em alguma lugar, e acessadas em outro. Ou melhor, elas são criadas e acessadas em u detirmado escopo. Falamos que existe como forma de simplificar, mas na realidade isso não existe.

A herança é entre classes (tipos), logo não ha necessidade de objetos e portanto não ha necessidade de runtime.

As regras de herança não são implementadas na compilação, elas ão forçadas na compilaçao.

Sim, somente nessa etapa.
Em runtime elas não são verificadas porque elas não existem em runtime. É por isso que a API de reflection funciona. E ai as regras são forçadas via API e passando pelo SecurityManager. Se o SecurityManager travar o acesso a coisas privadas vc não consegue acessar e ponto final.
Como eu já disse a JVM não força regras ela faz as coisas funcionar. Quem força regras é o compilador porque é no compilador que se define uma linguagem.

O ponto é esse. A classe receber os recursos da classe pai não significa que ha herança. Significa apenas que o estado do objeto precisa daquelas variáveis. Lembre-se que os métodos nem sequer existem na memoria.

Resumindo:
1)Herança é um conceito teorico que visa produzir tipos com base em outros existentes. Para isso ela aumenta o escopo da definição dos membros da classe.
2)Nem sempre tudo o que é de uma classe pode ser passado aos filhos. Por isso existe uma restrição que permite declarar uma variável apenas no escopo da classe onde ele é definida de forma que ela não pertence ao escopo da classe filha. Deste modo a classe filha não pode acessa essa variável. O uso de “private” garante, implica e foi criado para retirar a variável da herança. Serve para dizer “filho, isto, tu não herdas”.
3)Se a variável compoe o estado do objeto e o objeto é algo na memoria, provavelmente a memoria contém todas as variáveis privadas da hierarquia da classe do objeto, mas não ha forma de provar isso. Ferramentas de debug e afins não servem para provar a estrutura de memoria que a JVM usa (alías esse é todo o objetivo da JVM : encapsular a implementação)
4) Mesmo que as ferramentas mostrassem a real estrutura, e mesmo que essa estrutura contenha as variáveis privadas isso de deve ao facto da classe filha ser a classe pai, logo a variável está ali, porque o pai está ali.
Ele está, pertence, existe, é definida apenas no pai. nunca no filho. O objecto é definido pelo primeiro pai (objet) e acrescentado de todos os outros membros das classes filhas.

Enfim: membros private não são herdados.
É um contrasenso e um absurdo dizer que são. Esse é todo o objetivo deles serem declarados private.


Java tem uma excelente sintaxe porque é simples. com poucas palavras chave.
Poderiamos pensar que numa sintaxe maior a restrição de herança fosse definida com outra palavra
por exemplo “notinherit”. Seria mais explicito que aquele menbro não será herdado. Isto continuaria produzindo em memoria uma estrutura completa, porque “herdar” não significa “existe na memoria”, significa “existe no escopo”. Java é muito mais limpo na sintax e impede a herança de membros com private e a herança de classes com final.

Dieval_Guizelini

Sergio,

Quando estava lendo para acrescentar mais algum argumento em prol da minha teoria, econtrei um trecho no livro Java: O Guia essencial de David Flanagan que coloca esta questão dessa forma:

A especificação de java afirma que uma subclasse herda todos os campos de instância e métodos de instância (...)
A afirmação de que uma subclasse não herda os campos e métodos inacessíveis de sua superclasse pode gerar confusão. Aparentemente, essa afirmação indicaria que, quando você cria uma instância de uma subclasse, nenhuma memória é alocada a qualquer campo private definidos pela superclasse. Essa, porém, não é a intenção da afirmação. Cada instância de uma subclasse inclui, de fato, uma instância completa da superclasse dentro dela, incluindo todos os campos e métodos inacessíveis. Trata-se apenas de uma questão de terminologia. Como os campos inacessíveis não podem ser utilizados na subclasse, dizemos que eles não são herdados. (...)

A questão para mim ficou clara com relação ao sentido semantico, o conceito de herança está sendo associado a questão de usuabilidade pela subclasse e não da forma que eu vejo (que é quanto a composição ou consistência).

A diferença desses dois contextos, apresenta-se de forma clara no exemplo a seguir:

public class A {
   private int a=1;
   private int b=1;
   public void setA(int a) { this.a = a; }
   public int getA() { return this.a; }
   public void setB(int b) { this.b = b; }
   public int getB() { return this.b; }
}

public class B extends A {
   public int quadradoA() {
      return this.getA() * this.getA();
   }
}

public class C extends B {
   public int quadradoB() {
      return this.getB() * this.getB();
   }
}

Se os campos private não fossem herdados (estruturalmente), os métodos que fazem uso dos recursos getA e getB não poderiam funcionar, simplesmente porque o espaço de memória para os campos a e b não deveria existir.

fw

sergiotaborda

Otimo que entendeu.

Ora ai é que está. Funcionaria sim. Leia a sua citação de novo:
“Cada instância de uma subclasse inclui, de fato, uma instância completa da superclasse dentro dela, incluindo todos os campos e métodos inacessíveis”

Imagine dois retangulos . um menor a classe pai e um maior a classe filho. O maior não é um outro retangulo cujo conteudo foi copiado do pai e acrecentado de novas coisas. O maior é o pai acrecentado de novas coisas (sem copia). Então os campos podem não ser herdados e continuaram pertencendo na estrutrura do filho. Aliás , seria absurdo se não pertencecem.A diferença é que a estrutura do filho não é uma copia do pai e sim o pai em si mesmo. Assim asseguramos que os campos que pertencem a um nivel da hirarquia pertencem apenas a esse nivel.

Ainda bem que estamos esclarecidos quanto ao significado de herança e que ele nada tem a haver com estrutura na memoria.

Portanto, membros privados não são herdados.

Dieval_Guizelini

sergiotaborda:
Dieval Guizelini:

A questão para mim ficou clara com relação ao sentido semantico, o conceito de herança está sendo associado a questão de usuabilidade pela subclasse e não da forma que eu vejo (que é quanto a composição ou consistência).

Otimo que entendeu.

Eu compreendi o seu ponto de vista, não afirmei que o meu estava errado, e enquanto entedimento e interpretação do conceito de herança continuo defendendo o meu ponto de vista. Eu apenas encontrei uma literatura que descreve formalmente as diferenças de opnião.
O seu foco, para interpretação do conceito de herança, está na usuabilidade do recurso.
O meu foco, para interpretação do conceito de herança, está na existência do recurso (presente na classe filha, independente de estar acessivel diretamente ou não).

A afirmação não é minha, é do David Flanagan.

O exemplo serve para os dois casos.

sergiotaborda:

Ainda bem que estamos esclarecidos quanto ao significado de herança e que ele nada tem a haver com estrutura na memoria.
Portanto, membros privados não são herdados.

A afirmação em negrito é a sua interpretação do conceito para a forma com que o Java implementa o recurso de herança.

Como vivemos em uma democrácia, podemos conviver com as duas interpretações, e diria mais, que elas, na essencia, são complementares. Pois temos o aspecto da existência da estrutura de informação que está mais do que demonstranda que na classe filha recebe (herda) todas as características definidas na classe pai (independente da visibilidade). E com relação a usuabilidade desses recursos, podemos aceitar o fato que a classe filha não herda da classe pai os recursos, simplesmente pelo fato deles não estarem disponíveis para serem acessados diretamente.

Logo, para mim, a definição do conceito de herança para recursos privados, é melhor descrito como:

Uma subclasse recebe todos os campos e métodos da classe pai, porém os recursos privados (private) definidos na classe pai não estarão acessíveis diretamente pela subclasse.

Teremos ainda que ampliar a definição da exceção para recursos que são declarados sem o uso de um dos modificadores de acesso (public, private protected) para subclasses que não estejam no mesmo package da classe pai.

:lol:

alps

Galera, o negocio é o seguinte… Ao meu ver, os modificadores public, privated, protected etc… não controlam nada a respeito de herança e sim e somente a respeito de visibilidade externa (public: visivel para todos, privated: oculto para todos e protected: visivel para os filhos da classe) Tanto que se vc fizer uma classe Pessoa com atributos nome e idade PRIVADOS, mas contruir os getters e setters PROTEGIDOS (protected) vc poderá ter acesso a estes atributos por um objeto filho que por definição herdará todas as propriedades de sua SuperClass. :lol:

Criado 21 de dezembro de 2007
Ultima resposta 23 de nov. de 2008
Respostas 87
Participantes 31