Como você acessaria as propriedades do objeto de dentro de um método de objeto? [fechadas]

96

Qual é a maneira "purista" ou "correta" de acessar as propriedades de um objeto de dentro de um método de objeto que não seja um método getter / setter?

Eu sei que de fora do objeto você deve usar um getter / setter, mas de dentro você apenas faria:

Java:

String property = this.property;

PHP:

$property = $this->property;

ou você faria:

Java:

String property = this.getProperty();

PHP:

$property = $this->getProperty();

Perdoe-me se meu Java está um pouco errado, já faz um ano que programei em Java ...

EDITAR:

Parece que as pessoas estão presumindo que estou falando apenas de variáveis ​​/ propriedades privadas ou protegidas. Quando aprendi OO, fui ensinado a usar getters / setters para cada propriedade, mesmo que fosse pública (e, na verdade, me disseram para nunca tornar nenhuma variável / propriedade pública). Portanto, posso estar partindo de uma falsa suposição desde o início. Parece que as pessoas que respondem a esta pergunta talvez estejam dizendo que você deve ter propriedades públicas e que elas não precisam de getters e setters, o que vai contra o que me ensinaram e sobre o que eu estava falando, embora talvez isso precise ser discutido como bem. Este é provavelmente um bom tópico para uma pergunta diferente ...

cmcculloh
fonte

Respostas:

62

Isso tem potencial de guerra religiosa, mas me parece que se você estiver usando um getter / setter, você deve usá-lo internamente também - usar ambos levará a problemas de manutenção no futuro (por exemplo, alguém adiciona código a um setter que precisa para ser executado sempre que essa propriedade for definida e a propriedade estiver sendo definida internamente sem que o configurador seja chamado).

Greg Hurlman
fonte
não está fazendo mais nada em um setter além de definir o valor da propriedade, um exemplo de uso incorreto em Java.
euforia83
1
@ euphoria83 Talvez, mas isso não impede que aconteça.
Greg Hurlman
Eu concordo com a resposta original. No entanto, lembre-se de que, se estiver configurando ou obtendo algo privado dentro da classe ou objeto, você precisa ter certeza de que o getter / setter não é cíclico ou redundante de alguma forma que faça com que seu código falhe. Se você não puder usar o getter / setter, acesse-o diretamente. (Ex. Seu getter / setter acessa um método secundário (privado / protegido) para manipular os dados.)
Rick Mac Gillis
43

Pessoalmente, sinto que é importante permanecer consistente. Se você tiver getters e setters, use-os. A única vez que eu acessaria um campo diretamente é quando o acessador tem muita sobrecarga. Pode parecer que você está inchando seu código desnecessariamente, mas certamente pode evitar muita dor de cabeça no futuro. O exemplo clássico:

Mais tarde, você pode querer mudar a maneira como esse campo funciona. Talvez deva ser calculado instantaneamente ou talvez você queira usar um tipo diferente para a loja de apoio. Se você está acessando propriedades diretamente, uma mudança como essa pode quebrar uma quantidade enorme de código em um único foco.

MojoFilter
fonte
26

Estou bastante surpreso com o quão unânime é o sentimento de que os getterslevantadores são bons e bons. Sugiro o artigo incendiário de Allen Holub " Getters And Setters Are Evil ". Concedido, o título é para valor de choque, mas o autor apresenta pontos válidos.

Essencialmente, se você tem getterse setterspara todos os campos privados, está tornando esses campos tão bons quanto públicos. Você teria muita dificuldade em alterar o tipo de um campo privado sem efeitos de ondulação para cada classe que o chama getter.

Além disso, de um ponto de vista estritamente OO, os objetos devem responder a mensagens (métodos) que correspondem à sua (esperançosamente) única responsabilidade. A grande maioria de getterse settersnão faz sentido para seus objetos constituintes; Pen.dispenseInkOnto(Surface)faz mais sentido para mim do que Pen.getColor().

Os getters e setters também incentivam os usuários da classe a solicitar alguns dados ao objeto, realizar um cálculo e, em seguida, definir algum outro valor no objeto, mais conhecido como programação procedural. Seria melhor você simplesmente dizer ao objeto para fazer o que você estava fazendo em primeiro lugar; também conhecido como idioma do especialista em informações .

Getters e setters, no entanto, são males necessários na fronteira das camadas - UI, persistência e assim por diante. O acesso restrito aos elementos internos de uma classe, como a palavra-chave friend do C ++, o acesso protegido por pacote Java, o acesso interno do .NET e o Friend Class Pattern podem ajudar a reduzir a visibilidade getterse os setters apenas para aqueles que precisam deles.

moffdub
fonte
19

Depende de como a propriedade é usada. Por exemplo, digamos que você tenha um objeto aluno com uma propriedade de nome. Você pode usar o método Get para obter o nome do banco de dados, se ainda não tiver sido recuperado. Dessa forma, você está reduzindo chamadas desnecessárias ao banco de dados.

Agora, digamos que você tenha um contador inteiro privado em seu objeto que conta o número de vezes que o nome foi chamado. Você pode querer não usar o método Get de dentro do objeto porque ele produziria uma contagem inválida.

Shawn
fonte
Se o objeto Aluno for um objeto de negócio / domínio, agora você está misturando detalhes de infraestrutura. Idealmente, os objetos de negócios / domínio devem se preocupar apenas com a lógica de negócios / domínio.
moffdub
E se você adicionar algum tipo de booleano ao getter, como: PHP: public function getName ($ outsideCall = true) {if ($ outsideCall) {$ this-> incrementNameCalled (); } return $ this-> name; } e então de dentro do próprio Objeto, se você chamar get name, poderá evitar que ele seja incrementado por: PHP: $ name = $ this-> getName (false); Estou exagerando aqui?
cmcculloh
14

PHP oferece uma infinidade de maneiras de lidar com isso, incluindo métodos mágicos __gete __set, mas eu prefiro getters e setters explícitos. Aqui está o porquê:

  1. A validação pode ser colocada em setters (e getters para esse assunto)
  2. Intellisense funciona com métodos explícitos
  3. Não há dúvida se uma propriedade é somente leitura, somente gravação ou leitura-gravação
  4. A recuperação de propriedades virtuais (ou seja, valores calculados) é semelhante a propriedades regulares
  5. Você pode facilmente definir uma propriedade de objeto que nunca é realmente definida em qualquer lugar, que então fica em situação irregular
Carne Não Rotulada
fonte
13

Estou exagerando aqui?

Possivelmente ;)

Outra abordagem seria utilizar um método privado / protegido para realmente fazer a obtenção (armazenamento em cache / db / etc) e um wrapper público para ele que incrementa a contagem:

PHP:

public function getName() {
    $this->incrementNameCalled();
    return $this->_getName();
}

protected function _getName() {
    return $this->name;
}

e então de dentro do próprio objeto:

PHP:

$name = $this->_getName();

Dessa forma, você ainda pode usar o primeiro argumento para outra coisa (como enviar um sinalizador para usar ou não dados em cache aqui, talvez).

pix0r
fonte
12

Devo estar perdendo o ponto aqui, por que você usaria um getter dentro de um objeto para acessar uma propriedade desse objeto?

Levando isso a sua conclusão, o getter deve chamar um getter, que deve chamar um getter.

Então, eu diria que dentro de um método de objeto acessar uma propriedade diretamente, especialmente vendo como chamar outro método nesse objeto (que apenas acessará a propriedade diretamente de qualquer maneira e depois a retornará) é apenas um exercício inútil e inútil (ou eu entendi mal a questão )

Egg Vans
fonte
Fui movido pela mesma necessidade que você tinha de comentar ... Além disso, foi respondido não fechado;)
Egg Vans
8

A maneira OO purista é evitar ambos e seguir a Lei de Deméter usando a abordagem Diga, Não Pergunte .

Em vez de obter o valor da propriedade do objeto, que acopla as duas classes, use o objeto como parâmetro, por exemplo

  doSomethingWithProperty() {
     doSomethingWith( this.property ) ;
  }

Onde a propriedade era um tipo nativo, por exemplo, int, use um método de acesso, nomeie-o para o domínio do problema, não o domínio de programação.

  doSomethingWithProperty( this.daysPerWeek() ) ;

Isso permitirá que você mantenha o encapsulamento e quaisquer pós-condições ou invariantes dependentes. Você também pode usar o método setter para manter quaisquer pré-condições ou invariantes dependentes, no entanto, não caia na armadilha de nomeá-los setters, volte ao Princípio de Hollywood para nomear ao usar o idioma.

Martin Spamer
fonte
8

É melhor usar os métodos acessadores, mesmo dentro do objeto. Aqui estão os pontos que vêm à minha mente imediatamente:

  1. Deve ser feito no interesse de manter a consistência com os acessos feitos de fora do objeto.

  2. Em alguns casos, esses métodos de acesso podem fazer mais do que apenas acessar o campo; eles podem estar fazendo algum processamento adicional (embora isso seja raro). Se for esse o caso, acessar o campo diretamente significaria que você está perdendo aquele processamento adicional e seu programa pode dar errado se esse processamento sempre for feito durante esses acessos.

Aadith Ramia
fonte
8

Se você quer dizer "mais encapsulamento" por "purista", então geralmente declaro todos os meus campos como privados e uso "this.field" de dentro da própria classe. Para outras classes, incluindo subclasses, eu acesso o estado da instância usando os getters.

Allain Lalonde
fonte
7

Eu descobri que usar setters / getters tornou meu código mais fácil de ler. Também gosto do controle que ele dá quando outras classes usam os métodos e se eu alterar os dados que a propriedade armazenará.

Brendon-Van-Heyzen
fonte
7

Campos privados com propriedades públicas ou protegidas. O acesso aos valores deve passar pelas propriedades e ser copiados para uma variável local se forem usados ​​mais de uma vez em um método. Se e APENAS se você tiver o resto de seu aplicativo totalmente ajustado, bombado e otimizado de outra forma para que acessar valores por meio de suas propriedades associadas tenha se tornado um gargalo (E isso nunca acontecerá NUNCA, eu garanto) se você mesmo começar considerar deixar qualquer coisa diferente das propriedades tocar suas variáveis ​​de apoio diretamente.

Os desenvolvedores .NET podem usar propriedades automáticas para impor isso, já que você nem consegue ver as variáveis ​​de apoio no momento do design.

Mel
fonte
7

Depende. É mais uma questão de estilo do que qualquer outra coisa e não existe uma regra rígida.

Steve McLeod
fonte
7

Posso estar errado porque sou autodidata, mas NUNCA uso propriedades públicas em minhas classes Java, elas são sempre privadas ou protegidas, de modo que o código externo deve ser acessado por getters / setters. É melhor para fins de manutenção / modificação. E para código de classe interno ... Se o método getter for trivial, eu uso a propriedade diretamente, mas sempre uso os métodos setter porque poderia facilmente adicionar código para disparar eventos, se desejar.

Telcontar
fonte
7

Se eu não editar a propriedade, usarei um método público, a get_property()menos que seja uma ocasião especial, como um objeto MySQLi dentro de outro objeto. Nesse caso, tornarei a propriedade pública e me referirei a ela como $obj->object_property.

Dentro do objeto, é sempre a propriedade $ this-> para mim.

Ross
fonte
5

Bem, parece que com a implementação padrão das propriedades do C # 3.0, a decisão é tomada por você; você TEM que definir a propriedade usando o configurador de propriedade (possivelmente privado).

Pessoalmente, só uso o membro-atrás privado quando não faço isso faria com que o objeto caísse em um estado inferior ao desejável, como ao inicializar ou quando o cache / carregamento lento está envolvido.

Coincoin
fonte
5

Gosto da resposta de cmcculloh , mas parece que a mais correta é a de Greg Hurlman . Use getter / setter o tempo todo se você começou a usá-los desde o início e / ou está acostumado a trabalhar com eles.

À parte, eu pessoalmente acho que usar getter / setter torna o código mais fácil de ler e depurar posteriormente.

Robinho
fonte
4

Conforme afirmado em alguns dos comentários: Às vezes você deveria, às vezes não. A grande parte das variáveis ​​privadas é que você pode ver todos os lugares em que são usadas quando você muda algo. Se o seu getter / setter faz algo de que você precisa, use-o. Se não importa, você decide.

O caso oposto pode ser feito se você usar o getter / setter e alguém alterar o getter / setter, eles terão que analisar todos os lugares em que o getter e o setter são usados ​​internamente para ver se há alguma bagunça.

svrist
fonte