Objetos estruturais como em Java

195

É completamente contra a maneira Java de criar objetos semelhantes a estruturas?

class SomeData1 {
    public int x;
    public int y;
}

Eu posso ver uma classe com acessadores e mutadores mais parecidos com Java.

class SomeData2 {
    int getX();
    void setX(int x);

    int getY();
    void setY(int y);

    private int x;
    private int y;
}

A classe do primeiro exemplo é notávelmente conveniente.

// a function in a class
public int f(SomeData1 d) {
    return (3 * d.x) / d.y;
}

Isto não é tão conveniente.

// a function in a class
public int f(SomeData2 d) {
    return (3 * d.getX()) / d.getY();
}
Chris de Vries
fonte
9
Em vez de campos mutáveis ​​públicos, considere campos imutáveis ​​públicos ou campos mutáveis ​​locais do pacote. Ou seria melhor IMHO.
Peter Lawrey
Lembre-se de que, embora os getters e os setters sejam feios / detalhados, esse é o coração do Java. É uma linguagem não concisa. Por outro lado, você NUNCA deve digitar nada disso, pois é isso que o seu IDE faz por você. Em um idioma dinâmico, você precisa digitar menos, mas precisa digitar (geralmente, embora os IDEs possam ajudar).
Dan Rosenstark
Ironicamente, enquanto o OO tem seus pontos fortes em termos de encapsulamento, há um preço a ser pago pela CPU e pelo armazenamento. O coletor de lixo (quase completamente) remove a necessidade de se preocupar quando as referências de objetos devem ser limpas. A tendência atual está girando em círculo, empregando estruturas do tipo C fora da pilha. É perfeito para soluções do tipo cache, comunicações entre processos, operações mais intensivas em memória, menor GC / h e pode até se beneficiar de menor armazenamento / h para seus conjuntos de dados. Se você sabe o que está fazendo, não faria essa pergunta ... então pense novamente!
usar o seguinte comando
@ user924272: Re "A tendência atual está em um círculo completo ao empregar estruturas do tipo C fora da pilha". O que você faria em Java como ??? IMHO, esta é uma área onde Java está mostrando sua idade ...
ToolmakerSteve
@ToolmakerSteve -Estou vendo um círculo. Eu não sou o único. Empresas como a Azul estão interessadas na coleta de lixo sem pausa. Java é antigo. Verdade. Engenheiros que identificam uma fraqueza e fazem algo a respeito, em vez de gemer? Eles merecem respeito! +10 para Azul de mim :-)
user924272

Respostas:

62

Este é um tópico comumente discutido. A desvantagem de criar campos públicos em objetos é que você não tem controle sobre os valores definidos para ele. Em projetos de grupo em que existem muitos programadores usando o mesmo código, é importante evitar efeitos colaterais. Além disso, às vezes é melhor retornar uma cópia do objeto do campo ou transformá-lo de alguma forma etc. Você pode zombar de tais métodos em seus testes. Se você criar uma nova classe, poderá não ver todas as ações possíveis. É como uma programação defensiva - algum dia, getters e setters podem ser úteis, e não custa muito para criar / usá-los. Então, às vezes, são úteis.

Na prática, a maioria dos campos possui getters e setters simples. Uma solução possível seria assim:

public property String foo;   
a->Foo = b->Foo;

Atualização: É altamente improvável que o suporte à propriedade seja adicionado no Java 7 ou talvez nunca. Outros idiomas da JVM, como Groovy, Scala, etc, suportam esse recurso agora. - Alex Miller

Bartosz Bierkowski
fonte
28
Isso é muito ruim, eu como C # propriedades -estilo (que soa como o que você está falando)
Jon Onstott
2
Portanto, use sobrecarga ... private int _x; vazio público x (valor int) {_x = value; } public int x () {return _x; }
Gordon
12
Eu prefiro poder usar =, o que, na minha opinião, torna o código mais limpo.
Svish
6
@ T-Bull: Só porque você PODE ter dois xs que são duas coisas diferentes, não faz uma boa idéia. IMHO, essa é uma sugestão ruim, pois pode levar à confusão de leitores humanos. Princípio básico: não faça o leitor dar uma olhada dupla; torne óbvio o que você está dizendo - Use nomes diferentes para entidades diferentes. Mesmo que a diferença seja meramente acrescentar um sublinhado. Não confie na pontuação circundante para diferenciar as entidades.
precisa
2
@ToolmakerSteve: que "pode ​​levar à confusão" é o argumento mais comum e ainda o mais fraco quando se trata de defender o dogma de codificação (em oposição ao estilo de codificação). Sempre há alguém que pode ficar confuso com as coisas mais simples. Você sempre encontrará alguém reclamando que ele cometeu um erro depois de ficar acordado e codificando por meia semana ou algo assim e depois culpando o estilo de codificação enganoso. Eu não deixo isso contar. Esse estilo é válido, óbvio e mantém o espaço para nome limpo. Além disso, não há entidades diferentes aqui, há / one / entity e algum código padrão em torno dele.
T-Bull
290

Parece que muitas pessoas Java não estão familiarizadas com as Diretrizes de codificação Sun Java, que afirmam que é bastante apropriado usar a variável de instância pública quando a classe é essencialmente uma "Struct", se o Java suportou "struct" (quando não há comportamento).

As pessoas tendem a pensar que getters e setters são o caminho do Java, como se estivessem no coração do Java. Isto não é verdade. Se você seguir as Diretrizes de codificação Java da Sun, usando variáveis ​​de instância pública em situações apropriadas, estará realmente escrevendo um código melhor do que sobrecarregá-lo com getters e setters desnecessários.

Convenções de código Java de 1999 e ainda inalteradas.

10.1 Fornecendo acesso a variáveis ​​de instância e classe

Não torne pública nenhuma variável de instância ou classe sem uma boa razão. Freqüentemente, as variáveis ​​de instância não precisam ser explicitamente definidas ou obtidas, o que ocorre como efeito colateral das chamadas de método.

Um exemplo de variáveis ​​de instância pública apropriadas é o caso em que a classe é essencialmente uma estrutura de dados, sem comportamento. Em outras palavras, se você tivesse usado uma estrutura em vez de uma classe (se Java suportasse estrutura), será apropriado tornar públicas as variáveis ​​de instância da classe .

http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-137265.html#177

http://en.wikipedia.org/wiki/Plain_old_data_structure

http://docs.oracle.com/javase/1.3/docs/guide/collections/designfaq.html#28

developer.g
fonte
88
+1 Para realmente ter uma fonte autorizada. Todas as outras respostas são pessoas dando opiniões como se fossem fatos.
ArtOfWarfare
1
Há uma especificação do Java Beans que é uma maneira padrão do setor de acessar propriedades usando métodos get e set ... consulte en.wikipedia.org/wiki/JavaBeans para obter uma visão geral.
user924272
4
@ user924272: Como essa especificação do Java Beans é relevante para esta resposta, que discute quando é apropriado usar "variáveis ​​de instância pública"? Se a especificação fosse uma maneira padrão de transformar automaticamente variáveis ​​de instância em propriedades, como C #, pode ser relevante. Mas não é, né? Apenas especifica o nome dos getters e setters clichê que precisariam ser criados para fazer esse mapeamento.
precisa
@ToolmakerSteve. Esta é uma pergunta java. Além disso, a questão escapa a um problema comum onde existe uma especificação. Da perspectiva da velha escola, é muito mais fácil depurar mutações de campo quando existe uma maneira padrão de fazer isso - definir um ponto de interrupção em um setter. Provavelmente isso ficou obsoleto com os depuradores modernos, mas sou obrigado a desaprovar classes que diretamente "perfuram" objetos ... enquanto isso é bom para aplicativos menores, é uma verdadeira dor de cabeça para aplicativos maiores e grandes organizações
user924272
223

Use o bom senso realmente. Se você tem algo como:

public class ScreenCoord2D{
    public int x;
    public int y;
}

Então, não faz sentido envolvê-los em caçadores e caçadores. Você nunca vai armazenar uma coordenada x, y em pixels inteiros de qualquer outra maneira. Getters e setters apenas o atrasarão.

Por outro lado, com:

public class BankAccount{
    public int balance;
}

Convém alterar a maneira como um saldo é calculado em algum momento no futuro. Isso realmente deve usar getters e setters.

É sempre preferível saber por que você está aplicando boas práticas, para que você saiba quando é aceitável infringir as regras.

izb
fonte
3
Eu aceito esta resposta e digo mais que você pode criar uma classe com campos públicos, desde que os campos sejam em negrito independentes um do outro. isto é, um campo não depende de outro. Isso pode ser bastante útil em muitos casos, para múltiplos valores de retorno de uma função ou para co-odinados polares. {ângulo, comprimento} que caminham juntos, mas não dependem um do outro de maneira intrínseca.
Spacen Jasset
@SpacenJasset: FYI, não vejo como seus exemplos (vários valores de retorno; coordenadas polares) têm alguma influência sobre o uso de campos públicos versus getter / setters. No caso de múltiplos valores de retorno, pode até ser contraproducente, porque, sem dúvida, o chamador deve estar apenas GETTING os valores retornados, o que argumenta a favor de public getters e private setters (imutáveis). Isso também pode ser verdade para o retorno de coordenadas polares de um objeto (x, y) - considere erros matemáticos ACUMULARES, pois as alterações nos componentes individuais da coordenada polar são convertidas novamente em (x, y).
Home
@SpacenJasset: Mas eu concordo com o seu princípio.
precisa
1
Você tem um argumento válido, mas acho que a coisa dos pixels é um mau exemplo, pois garantir que o pixel esteja dentro da janela (apenas um exemplo) é algo que alguém pode fazer e, além disso, permitir que alguém defina o pixel (-5, -5)pode não ser uma boa ideia. :-)
Horsey 29/03
50

Para abordar questões de mutabilidade, você pode declarar x e y como finais. Por exemplo:

class Data {
  public final int x;
  public final int y;
  public Data( int x, int y){
    this.x = x;
    this.y = y;
  }
}

O código de chamada que tentar gravar nesses campos receberá um erro de tempo de compilação de "o campo x é declarado final; não pode ser atribuído".

O código do cliente pode ter a conveniência de 'mão curta' que você descreveu em sua postagem

public class DataTest {
    public DataTest() {
        Data data1 = new Data(1, 5);
        Data data2 = new Data(2, 4);
        System.out.println(f(data1));
        System.out.println(f(data2));
    }

    public int f(Data d) {
        return (3 * d.x) / d.y;
    }

    public static void main(String[] args) {
        DataTest dataTest = new DataTest();
    }
}
Brian
fonte
3
Obrigado - uma resposta que é útil e concisa. Mostra como obter o benefício da sintaxe de campo, quando não deseja mutabilidade.
precisa
@ ToolmakerSteve - obrigado pelo feedback - muito apreciado.
19714 Brian
Tentei usar instâncias finais de uma classe final com campos finais como struct "instâncias", mas em uma caseexpressão referente a esse campo de instância, obtive Case expressions must be constant expressions. qual é o caminho para contornar isso? qual é o conceito idiomático aqui?
N611x007
1
Os campos finais ainda são referências a objetos, que não são constantes, pois serão inicializados quando a classe for usada pela primeira vez. O compilador não pode saber o "valor" das referências de objeto. As constantes devem ser conhecidas ao compilar.
Johan Tidén 10/10
1
+1 resposta realmente importante. A utilidade de classes imutáveis ​​não pode ser subestimada em minha opinião. Sua semântica de "acionar e esquecer" torna o raciocínio sobre o código geralmente mais simples, especialmente em ambientes multithread, onde eles podem ser compartilhados arbitrariamente entre threads, sem sincronização.
TheOperator
11

Não use publiccampos

Não use publiccampos quando você realmente deseja entender o comportamento interno de uma classe. Tome java.io.BufferedReaderpor exemplo. Tem o seguinte campo:

private boolean skipLF = false; // If the next character is a line feed, skip it

skipLFé lido e escrito em todos os métodos de leitura. E se uma classe externa em execução em um thread separado modificasse maliciosamente o estado skipLFno meio de uma leitura? BufferedReaderdefinitivamente vai dar errado.

Use publiccampos

Veja esta Pointclasse, por exemplo:

class Point {
    private double x;
    private double y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }

    public double getX() {
        return this.x;
    }

    public double getY() {
        return this.y;
    }

    public void setX(double x) {
        this.x = x;
    }

    public void setY(double y) {
        this.y = y;
    }
}

Isso tornaria muito difícil escrever a distância entre dois pontos.

Point a = new Point(5.0, 4.0);
Point b = new Point(4.0, 9.0);
double distance = Math.sqrt(Math.pow(b.getX() - a.getX(), 2) + Math.pow(b.getY() - a.getY(), 2));

A classe não possui nenhum comportamento além de getters e setters simples. É aceitável usar campos públicos quando a classe representa apenas uma estrutura de dados, e não possui e nunca terá comportamento (getters e setters thin não são considerados comportamento aqui). Pode ser escrito melhor desta maneira:

class Point {
    public double x;
    public double y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
}

Point a = new Point(5.0, 4.0);
Point b = new Point(4.0, 9.0);
double distance = Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));

Limpar \ limpo!

Mas lembre-se: não apenas sua classe deve estar ausente de comportamento, mas também não deve ter motivos para ter comportamento no futuro.


(É exatamente isso que esta resposta descreve. Para citar "Convenções de código para a linguagem de programação Java: 10. Práticas de programação" :

Um exemplo de variáveis ​​de instância pública apropriadas é o caso em que a classe é essencialmente uma estrutura de dados, sem comportamento. Em outras palavras, se você usasse uma structclasse em vez de uma classe (se suportado por Java struct), é apropriado tornar públicas as variáveis ​​de instância da classe.

Portanto, a documentação oficial também aceita essa prática.)


Além disso, se você tiver certeza absoluta de que os membros da Pointclasse acima devem ser imutáveis, adicione a finalpalavra-chave para aplicá-la:

public final double x;
public final double y;
sampathsris
fonte
8

A propósito, a estrutura que você está dando como exemplo já existe na biblioteca de classes base Java como java.awt.Point. Tem x e y como campos públicos, confira você mesmo .

Se você sabe o que está fazendo e outras pessoas da sua equipe sabem disso, não há problema em ter campos públicos. Mas você não deve confiar nisso, pois eles podem causar dores de cabeça, como em bugs relacionados a desenvolvedores que usam objetos como se fossem estruturas alocadas em pilha (objetos java são sempre enviados aos métodos como referências e não como cópias).

Spoike
fonte
+1 Boa menção a um problema - uma maneira pela qual o resultado ainda não é como uma estrutura C. No entanto, o problema que você coloca sobre objetos java sempre sendo por referência não é aprimorado criando um setter em vez de ter um campo público gravável (que é a essência da pergunta do OP - qual representação usar). Pelo contrário, é um argumento a favor de NÃO fazer. É um argumento para IMUBILIDADE. O que pode ser feito como um public finalcampo, como na resposta de Brian, ou com um public getter, mas nenhum public setter. Ou seja, se alguém usa campos ou acessadores é irrelevante.
Home
8

Re: aku, izb, John Topley ...

Cuidado com os problemas de mutabilidade ...

Pode parecer sensato omitir getters / setters. Na verdade, pode estar ok em alguns casos. O verdadeiro problema com o padrão proposto mostrado aqui é a mutabilidade.

O problema é quando você passa uma referência de objeto contendo campos públicos não finais. Qualquer outra coisa com essa referência é livre para modificar esses campos. Você não tem mais controle sobre o estado desse objeto. (Pense no que aconteceria se Strings fossem mutáveis.)

Fica ruim quando esse objeto é uma parte importante do estado interno de outro, você acabou de expor a implementação interna. Para evitar isso, uma cópia do objeto deve ser retornada. Isso funciona, mas pode causar pressão maciça no GC a partir de toneladas de cópias de uso único criadas.

Se você tiver campos públicos, considere tornar a classe somente leitura. Adicione os campos como parâmetros ao construtor e marque os campos como finais. Caso contrário, verifique se você não está expondo o estado interno e, se precisar construir novas instâncias para um valor de retorno, verifique se não será chamado excessivamente.

Veja: " Java eficaz ", de Joshua Bloch - Item 13: Favor da imutabilidade.

PS: Lembre-se também de que todas as JVMs atualmente otimizam o getMethod, se possível, resultando em apenas uma única instrução de leitura de campo.

Mark Renouf
fonte
12
Como um getter / setter resolve esse problema. Você ainda tem uma referência, não possui sincronização com as operações. Os getters / setters não fornecem proteção por si mesmos.
23468 he_the_great #
1
Getters e setters podem fornecer sincronização, se necessário. Você também espera que getters e setter façam muito mais do que eles foram especificados. Independentemente disso, o problema da sincronização ainda persiste.
user924272
7

Eu tentei isso em alguns projetos, na teoria de que getters e setters confundem o código com um fragmento semanticamente sem sentido, e que outras linguagens parecem funcionar bem com ocultação de dados com base em convenções ou particionamento de responsabilidades (por exemplo, python).

Como outros observaram acima, existem 2 problemas nos quais você se depara e eles não são realmente corrigíveis:

  • Praticamente qualquer ferramenta automatizada no mundo java depende da convenção getter / setter. O mesmo vale para, como observado por outros, tags jsp, configuração de mola, ferramentas de eclipse, etc. etc ... Lutar contra o que suas ferramentas esperam ver é uma receita para longas sessões percorrendo o google tentando encontrar essa maneira não padrão de iniciar feijão de primavera. Realmente não vale a pena.
  • Depois de ter seu aplicativo codificado de forma elegante com centenas de variáveis ​​públicas, você provavelmente encontrará pelo menos uma situação em que elas são insuficientes - onde você absolutamente precisa de imutabilidade ou precisa acionar algum evento quando a variável é definida, ou você deseja lançar uma exceção em uma alteração de variável porque define um estado de objeto como algo desagradável. Você fica preso às escolhas inviáveis ​​entre desorganizar seu código com algum método especial em qualquer lugar em que a variável é diretamente referenciada, tendo algum formulário de acesso especial para 3 das 1000 variáveis ​​em seu aplicativo.

E este é, na melhor das hipóteses, trabalhar totalmente em um projeto privado independente. Depois que você exporta tudo para uma biblioteca acessível ao público, esses problemas se tornam ainda maiores.

Java é muito detalhado, e isso é uma coisa tentadora de se fazer. Não faça isso.

Steve B.
fonte
Excelente discussão sobre os problemas de seguir o caminho dos campos públicos. Uma falha definitiva do Java, que me irrita quando tenho que voltar ao Java a partir do C # (que aprendi com a inconveniência de Java aqui).
Página
4

Se o caminho Java é o caminho OO, sim, a criação de uma classe com campos públicos quebra os princípios em torno da ocultação de informações que dizem que um objeto deve gerenciar seu próprio estado interno. Portanto, como não estou falando apenas do jargão, um benefício da ocultação de informações é que o funcionamento interno de uma classe está oculto por trás de uma interface - digamos que você queira alterar o mecanismo pelo qual sua classe struct salvou um de seus campos, você provavelmente precisará voltar e alterar as classes que usam a classe ...)

Você também não pode tirar proveito do suporte às classes compatíveis com a nomeação JavaBean, o que prejudicará se você decidir, digamos, usar a classe em uma Página JavaServer que é escrita usando a Expression Language.

O artigo JavaWorld Por que os métodos Getter e Setter são maus também pode ser interessante para você pensar em quando não implementar métodos de acessador e mutador.

Se você está escrevendo uma solução pequena e deseja minimizar a quantidade de código envolvido, o caminho Java pode não ser o caminho certo - acho que sempre depende de você e do problema que você está tentando resolver.

brabster
fonte
1
+1 no link para o artigo "Por que os métodos Getter e Setter são maus". No entanto, sua resposta seria mais clara se você apontasse que AMBOS os campos públicos E os getter / setters públicos NÃO SÃO IGUALMENTE o caminho do Java: Conforme explicado no artigo - quando possível, não faça isso também. Em vez disso, forneça aos clientes métodos específicos para o que eles precisam fazer, em vez de espelhar a representação interna da instância. No entanto, isso realmente não aborda a pergunta que está sendo feita (qual usar, para um simples caso "struct"), que é melhor respondida por developer.g, izb e Brian.
precisa
3

Não há nada errado com esse tipo de código, desde que o autor saiba que são estruturas (ou shuttles de dados) em vez de objetos. Muitos desenvolvedores de Java não conseguem distinguir a diferença entre um objeto bem formado (não apenas uma subclasse de java.lang.Object, mas um verdadeiro objeto em um domínio específico) e um abacaxi. Logo, eles acabam escrevendo estruturas quando precisam de objetos e vice-versa.

luis.espinal
fonte
o abacaxi me fazer rir :)
Guillaume
No entanto, esta resposta não diz nada sobre o que é essa diferença. Ficar chateado com desenvolvedores não qualificados não ajuda esses desenvolvedores a saber quando criar uma estrutura e quando criar uma classe.
Home
Não diz nada sobre a diferença porque o autor está ciente da diferença (ele sabe o que é uma entidade semelhante a uma estrutura). O autor está perguntando se o uso de estruturas é apropriado em uma linguagem OO, e eu digo que sim (dependendo do domínio do problema). Se a pergunta era sobre o que faz de um objeto um objeto de domínio real, você teria uma perna na sua argumento.
Luis.espinal
Além disso, o único tipo de desenvolvedor não qualificado que não deveria saber a diferença seria aquele que ainda está na escola. Isso é extremamente fundamental, como saber a diferença entre uma lista vinculada e uma tabela de hash. Se uma pessoa se formar com um diploma de software de quatro anos sem saber o que é um objeto verdadeiro, essa pessoa não será cortada para esta carreira ou voltará à escola e exigirá um reembolso. Estou falando sério.
Luis.espinal
Mas, para satisfazer sua queixa, darei uma resposta (que tem pouco ou nada a ver com a pergunta original e que merece seu próprio tópico). Os objetos têm comportamento e encapsulam o estado. Estruturas não. Objetos são máquinas de estado. As estruturas são apenas para agregar dados. Se as pessoas querem uma resposta mais elaborada, elas são livres para criar uma nova pergunta, onde podemos elaborá-la para o conteúdo de nossos corações.
Luis.espinal
2

O problema de usar o acesso ao campo público é o mesmo que usar o método novo em vez do método de fábrica - se você mudar de idéia mais tarde, todos os chamadores existentes serão interrompidos. Portanto, do ponto de vista da evolução da API, geralmente é uma boa ideia morder a bala e usar getters / setters.

Um lugar onde eu vou para o outro lado é quando você controla fortemente o acesso à classe, por exemplo, em uma classe estática interna usada como uma estrutura de dados interna. Nesse caso, pode ser muito mais claro usar o acesso ao campo.

A propósito, na afirmação da e-bartek, é altamente improvável que a IMO suporte de propriedade seja adicionado no Java 7.

Alex Miller
fonte
1
Isso é verdade, mas se você estiver usando Java, não é uma preocupação, pois você pode refatorar toda uma base de código em um clique (Eclipse, Netbeans, provavelmente VIM e Emacs também). Se você optou por um de seus amigos dinâmicos, como o Groovy, mesmo um simples encapsulamento pode fazer você consertar por horas ou dias. Felizmente, você teria seus casos de teste que o informariam ... quanto mais código você precisa corrigir.
Dan Rosenstark
2
Você presume, é claro, que todos os usuários estão em sua base de código, mas é claro que isso geralmente não é verdade. Freqüentemente, nem por várias razões não técnicas é possível alterar o código que pode estar em sua própria base de código.
Alex Miller
2

Costumo usar esse padrão ao criar classes internas privadas para simplificar meu código, mas não recomendo expor esses objetos em uma API pública. Em geral, com mais freqüência você pode tornar imutáveis ​​os objetos em sua API pública, e não é possível construir seu objeto 'semelhante a uma estrutura' de maneira imutável.

Como um aparte, mesmo se eu estivesse escrevendo esse objeto como uma classe interna privada, eu ainda forneceria um construtor para simplificar o código para inicializar o objeto. Ter que ter 3 linhas de código para obter um objeto utilizável quando se faz é apenas confuso.

Kris Nuttycombe
fonte
2

Uma pergunta muito antiga, mas deixe-me fazer outra pequena contribuição. O Java 8 introduziu expressões lambda e referências a métodos. Expressões lambda podem ser simples referências de método e não declarar um corpo "verdadeiro". Mas você não pode "converter" um campo em uma referência de método. portanto

stream.mapToInt(SomeData1::x)

não é legal, mas

stream.mapToInt(SomeData2::getX)

é.

Lyubomyr Shaydariv
fonte
Neste caso, você pode usar data -> data.x, que ainda é razoável
James Kraus
1

Não vejo mal se você souber que sempre será uma estrutura simples e que nunca desejará anexar um comportamento a ela.

John Topley
fonte
1

Esta é uma pergunta sobre Design Orientado a Objetos, não sobre Java, a linguagem. Geralmente, é uma boa prática ocultar tipos de dados na classe e expor apenas os métodos que fazem parte da API da classe. Se você expuser tipos de dados internos, nunca poderá alterá-los no futuro. Se você os ocultar, sua única obrigação para com o usuário são os tipos de retorno e argumento do método.

Jonathan
fonte
1

Aqui, crio um programa para inserir Nome e Idade de 5 pessoas diferentes e realizar uma classificação (idade). Eu usei uma classe que atua como uma estrutura (como a linguagem de programação C) e uma classe principal para executar a operação completa. Abaixo estou fornecendo o código ...

import java.io.*;

class NameList {
    String name;
    int age;
}

class StructNameAge {
    public static void main(String [] args) throws IOException {

        NameList nl[]=new NameList[5]; // Create new radix of the structure NameList into 'nl' object
        NameList temp=new NameList(); // Create a temporary object of the structure

        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

        /* Enter data into each radix of 'nl' object */

        for(int i=0; i<5; i++) {
            nl[i]=new NameList(); // Assign the structure into each radix

            System.out.print("Name: ");
            nl[i].name=br.readLine();

            System.out.print("Age: ");
            nl[i].age=Integer.parseInt(br.readLine());

            System.out.println();
        }

        /* Perform the sort (Selection Sort Method) */

        for(int i=0; i<4; i++) {
            for(int j=i+1; j<5; j++) {
                if(nl[i].age>nl[j].age) {
                    temp=nl[i];
                    nl[i]=nl[j];
                    nl[j]=temp;
                }
            }
        }

        /* Print each radix stored in 'nl' object */

        for(int i=0; i<5; i++)
            System.out.println(nl[i].name+" ("+nl[i].age+")");
    }
}

O código acima é livre de erros e testado ... Basta copiá-lo e colá-lo no seu IDE e ... Você sabe e o que ??? :)

Avik Kumar Goswami
fonte
0

Você pode criar uma classe simples com campos públicos e sem métodos em Java, mas ainda é uma classe e ainda é tratada sintaticamente e em termos de alocação de memória, como uma classe. Não há como reproduzir genuinamente estruturas em Java.

cblades
fonte
0

Às vezes uso essa classe, quando preciso retornar vários valores de um método. Obviamente, esse objeto tem vida curta e visibilidade muito limitada, portanto deve estar OK.

PhiLho
fonte
0

Como na maioria das coisas, existe a regra geral e há circunstâncias específicas. Se você estiver executando um aplicativo capturado e fechado para saber como um determinado objeto será usado, poderá exercer mais liberdade para favorecer a visibilidade e / ou a eficiência. Se você estiver desenvolvendo uma classe que será usada publicamente por outras pessoas fora do seu controle, incline-se para o modelo getter / setter. Como em todas as coisas, use apenas o bom senso. Geralmente, não há problema em fazer uma rodada inicial com os públicos e depois alterá-los para getter / setters mais tarde.

Evvo
fonte
0

A programação orientada a aspectos permite capturar atribuições ou buscar e anexar lógica interceptadora a elas, o que proponho é o caminho certo para resolver o problema. (A questão de saber se eles devem ser públicos ou protegidos ou protegidos por pacotes é ortogonal.)

Assim, você começa com campos não interceptados com o qualificador de acesso certo. À medida que os requisitos do seu programa aumentam, você anexa a lógica para talvez validar, faça uma cópia do objeto que está sendo retornado etc.

A filosofia getter / setter impõe custos a um grande número de casos simples, onde eles não são necessários.

Se o estilo do aspecto é mais limpo ou não, é um pouco qualitativo. Eu acharia fácil ver apenas as variáveis ​​em uma classe e visualizar a lógica separadamente. De fato, a razão de ser da programação orientada a Apect é que muitas preocupações são transversais e compartimentá-las no próprio corpo da classe não é o ideal (o log é um exemplo - se você deseja registrar tudo, Java quer que você escreva um monte de getters e mantenha-os sincronizados, mas o AspectJ permite uma única linha).

A questão do IDE é um problema. Não é tanto a digitação, como a poluição visual e de leitura que surge dos get / sets.

As anotações parecem semelhantes à programação orientada a aspectos à primeira vista, no entanto, exigem que você enumere exaustivamente os cortes de ponto anexando anotações, em oposição a uma especificação concisa de corte de ponto do tipo curinga no AspectJ.

Espero que a conscientização sobre o AspectJ impeça as pessoas de optarem prematuramente por idiomas dinâmicos.

necromante
fonte