Usando atributos com código Ruby

Olhe para qualquer código orientado a objeto e tudo mais ou menos segue o mesmo padrão. Crie um objeto, chame alguns métodos e acesse os atributos desse objeto. Não há muito mais que você possa fazer com um objeto, exceto passá-lo como parâmetro para o método de outro objeto. Mas o que nos preocupa aqui são os atributos.

Os atributos são como variáveis ​​de instância você pode acessar através da notação de ponto do objeto. Por exemplo, person.name acessaria o nome de uma pessoa. Da mesma forma, você pode frequentemente atribuir a atributos como person.name = "Alice". Esse é um recurso semelhante às variáveis ​​de membro (como em C ++), mas não é o mesmo. Não há nada de especial acontecendo aqui, os atributos são implementados na maioria dos idiomas usando "getters" e "setters", ou métodos que recuperam e definem os atributos das variáveis ​​de instância.

Ruby não faz distinção entre getters e setters de atributos e métodos normais. Devido ao método flexível de Ruby chamar sintaxe, nenhuma distinção precisa ser feita. Por exemplo,

instagram viewer
person.name e person.name () são a mesma coisa, você está chamando o nome método com zero parâmetros. Um se parece com uma chamada de método e o outro se parece com um atributo, mas ambos são a mesma coisa. Ambos estão apenas chamando o nome método. Da mesma forma, qualquer nome de método que termine com um sinal de igual (=) pode ser usado em uma atribuição. A declaração person.name = "Alice" é realmente a mesma coisa que person.name = (alice), mesmo que exista um espaço entre o nome do atributo e o sinal de igual, ele ainda está apenas chamando o name = método.

Você pode facilmente implementar atributos você mesmo. Ao definir os métodos setter e getter, você pode implementar qualquer atributo que desejar. Aqui está um exemplo de código implementando o nome atributo para uma classe de pessoa. Ele armazena o nome em um @nome variável de instância, mas o nome não precisa ser o mesmo. Lembre-se, não há nada de especial nesses métodos.

Uma coisa que você notará imediatamente é que isso dá muito trabalho. É muita digitação apenas para dizer que você deseja um atributo chamado nome que acessa o @nome variável de instância. Felizmente, Ruby fornece alguns métodos de conveniência que definirão esses métodos para você.

Existem três métodos no Módulo classe que você pode usar dentro de suas declarações de classe. Lembre-se de que Ruby não faz distinção entre tempo de execução e "tempo de compilação", e qualquer código dentro das declarações de classe pode não apenas definir métodos, mas também chamar métodos. Chamando o attr_reader, attr_writer e attr_accessor os métodos, por sua vez, definirão os setters e getters que estávamos nos definindo na seção anterior.

o attr_reader O método é exatamente o que parece. É necessário qualquer número de parâmetros de símbolo e, para cada parâmetro, define um método "getter" que retorna a variável de instância com o mesmo nome. Então, podemos substituir nossa nome método no exemplo anterior com attr_reader: nome.

Da mesma forma, o attr_writer O método define um método "setter" para cada símbolo passado para ele. Observe que o sinal de igual não precisa fazer parte do símbolo, apenas o nome do atributo. Nós podemos substituir o name = método do exemplo anterior com uma chamada para attr_writier: nome.

E, como esperado, attr_accessor faz o trabalho de ambos attr_writer e attr_reader. Se você precisar de um setter e um getter para um atributo, é prática comum não chamar os dois métodos separadamente e, em vez disso, chamar attr_accessor. Nós poderíamos substituir ambos a nome e name = métodos do exemplo anterior com uma única chamada para attr_accessor: nome.

Por que você deve definir setters manualmente? Por que não usar o attr_ * métodos toda vez? Porque eles quebram o encapsulamento. O encapsulamento é o principal que afirma que nenhuma entidade externa deve ter acesso irrestrito ao estado interno do seu objetos. Tudo deve ser acessado usando uma interface que impeça o usuário de corromper o estado interno do objeto. Usando os métodos acima, perfuramos um grande buraco em nossa parede de encapsulamento e permitimos que qualquer coisa fosse definida para um nome, mesmo nomes obviamente inválidos.

Uma coisa que você verá frequentemente é que attr_reader será usado para definir rapidamente um getter, mas um setter personalizado será definido, pois o estado interno do objeto geralmente deseja ser ler diretamente do estado interno. O setter é então definido manualmente e faz verificações para garantir que o valor que está sendo definido faça sentido. Ou, talvez mais comumente, nenhum levantador seja definido. Os outros métodos na função de classe configuram a variável de instância atrás do getter de alguma outra maneira.

Agora podemos adicionar um era e implementar adequadamente um nome atributo. o era O atributo pode ser definido no método construtor, lido usando o era getter, mas apenas manipulado usando o have_birthday método, que aumentará a idade. o nome O atributo tem um getter normal, mas o setter garante que o nome seja maiúsculo e esteja na forma de Primeiro nome, ultimo nome.

instagram story viewer