DEV Community

Cover image for Orientação a Objetos com Ruby (Parte 2) - Objetos e Classes
Daniel Moreto
Daniel Moreto

Posted on • Edited on

Orientação a Objetos com Ruby (Parte 2) - Objetos e Classes

Fala comiigo!

Dando continuidade à série de Orientação a Objetos com Ruby, nesse post começaremos a falar da parte mais técnica e tentar entender o que é de fato um objeto e como ele se comporta na Programação Orientada a Objetos.

Vamos lá, Objetos...

O que é Objeto?

Nós podemos podemos pensar em Objetos como a representação de algo do mundo real. Eu sei que pode parecer um pouco aleatório isso, mas a ideia da orientação a objetos é que nós possamos literalmente representar qualquer coisa que esteja presente no nosso mundo, seja tangível ou intangível.

Exemplos disso seriam: um computador, um celular, seu animal de estimação, a casa onde você mora, a cadeira que você senta, tudo.

Poderia inclusive ser você, que enquanto trabalhador exerce a sua profissão todos os dias, ou aquela cafeteria que você vai tomar um cafezinho às vezes. Ou seja, você, seu registro de ponto, a cafeteria, o seu café, a comanda que você recebe, tudo isso pode ser um objeto na Programação Orientada a Objetos (POO).

Pois bem, fica com isso na cuca que a gente precisa adicionar uns detalhes...

Interação dos Objetos com o Mundo

Vamos fazer uma observação do mundo real. Pensa naquela cafeteria, numa pessoa atendente que está lá todo santo dia trabalhando. Imagine que ela, que aqui vamos chamar de Maria, trabalha 10h por dia contando sábados e domingos, entra às 4:00h e sai apenas às 14:00h.

Que tipo de informações conseguimos extrair fazendo essa observação?

  • Provavelmente é uma pessoa trabalhadora super explorada
  • O nome dessa pessoa é Maria
  • A carga horária de trabalho é de 60h semanais
  • Horário que ela entra é 4:00h
  • Horário que ela sai é às 14:00h

E como essa trabalhadora interage com o mundo real enquanto atendente desta cafeteria?

  • Abre comanda
  • Anota pedido
  • Registra o ponto

Vamos pensar se você foi até esta cafeteria e a Maria, ao te atender, abriu uma comanda de número 5142 para a sua mesa de número 17. Você pediu à Maria um cafezinho pingado e um pão de queijo. Que características conseguimos extrair dessa situação?

  • O número da comanda é 5142
  • A mesa que ela atende é 17
  • Os itens são um café pingado e um pão de queijo
  • A pessoa atendente é Maria

E como essa comanda pode "interagir" com o mundo?

  • Ela pode receber um novo item
  • Um item pode ser removido dela
  • Pode ser fechada

Então, pega a visão: todo objeto tem características e comportamentos.

Se tiver animado, faça esse exercício: olhe à sua volta e anote as carecterísticas e comportamentos você consegue extrair dos objetos que identifica.

Tá, Objeto foi.. E Classe?

Vamos voltar à comanda, onde seu pedido é anotado.

Quando paramos pra pensar, aquele pedaço de papel dividido como uma tabela que tem um número, os itens que você consumiu e o número da sua mesa é apenas uma das possíveis que a Maria vai abrir. Milhares de outras vão existir antes e depois da sua.

Porém, todos estes pedaços de papel tem uma classificação, ou uma Classe, algo que a define, algo que diz todas as caraterísticas e os comportamentos que esse papel conhecido como Comanda precisa ter. Ou seja, a Classe é o esqueleto do Objeto.

Para que a sua comanda exista com o número 5142, com o seu café pingado e seu pão de queijo, com o número da sua mesa 17 e associada à pessoa atendente Maria, ela precisa de um molde, esse molde é a Classe.

A partir da Classe nós definimos quais características e comportamentos os Objetos existirão.

E o código, heim?! E o Ruby?!

Nos exemplos de código, nós utilizaremos a Comanda.

Bem, todo Objeto surge a partir de uma Classe definida, então se quisermos representar a Comanda, nós precisamos criar uma Classe pra ela, e no Ruby seria desta forma:

class Comanda
end
Enter fullscreen mode Exit fullscreen mode

A palavra-chave class é utilizada para definir uma classe.

Com esta classe criada, se quisermos criar um Objeto a partir dela, faremos

class Comanda
end

minha_comanda = Comanda.new
Enter fullscreen mode Exit fullscreen mode

Com o Comanda.new criamos um objeto Comanda e armazenamos na variável minha_comanda. Nós estamos criando somente um objeto, mas não existe um limite que nos impeça de criar mais 2 ou mais 1000 com a mesma classe.

Adicionando Comportamento na Classe

Como vimos, a Comanda possui comportamentos que define as ações que um objeto pode exercer. No Ruby, toda e qualquer comunicação do Objeto com o mundo real ocorre por meio da definição de Métodos. E se você veio de outro paradigma de programação, o método é uma função dentro de uma Classe.

Vamos pegar como o exemplo o comportamento "ser fechada". Para que a Comanda tenha o comportamento de ser fechada, nós vamos criar um método chamado fechar dentro dela desta forma:

class Comanda
  def fechar
    puts "Comanda fechada!"
  end
end

...
Enter fullscreen mode Exit fullscreen mode

Uma vez que definimos o método fechar na classe, nós podemos chamá-lo no objeto desta forma:

class Comanda
  ...
end

minha_comanda = Comanda.new
minha_comanda.fechar
Enter fullscreen mode Exit fullscreen mode

Lembrando que quando definimos o fechar ali em cima, nós estamos declarando como o objeto vai se comportar quando este método for chamado. Com isso, você verá que o seguinte texto será impresso na sua tela:

Comanda fechada!
Enter fullscreen mode Exit fullscreen mode

Este foi apenas um exemplo de um método, a ideia é que futuramente ele faça coisas significativas em vez de só imprimir coisas na tela =)

Adicionamos um primeiro comportamento, agora precisamos também adicionar as características.

Definindo as Características

Na POO, as características de um objeto são conhecidas como Atributos.

Uma particularidade do Ruby é que TODO e qualquer atributo de um objeto é privado ao próprio objeto. Um atributo NUNCA será manipulado ou acessado diretamente do mundo exterior ao objeto.

Você deve estar se perguntando, então pra que raios eu vou precisar de um atributo?!?!...

Pois bem, repetindo, ele realmente NUNCA será manipulado ou acessado diretamente do mundo exterior ao objeto, MAS o objeto pode fornecer meios desses atributos serem manipulados se forma indireta. Lembra que eu te falei que "toda e qualquer comunicação do Objeto com o mundo real ocorre por meio da definição de Métodos"? Nós também utilizaremos os métodos para manipular os atributos de um objeto.

Retomando a nossa Comanda, nós vimos que ela tem as características como número da comanda, número da mesa, lista de itens e quem é a atendente. E assumiremos que a partir destas características nós vamos definir os atributos numero para o numero da comanda, mesa para o número da mesa, itens para a lista de itens e atendente para o nome da pessoa que te atendeu.

Para que uma Comanda possa receber um número, criaremos um método que vai atribuir este valor num atributo numero. Para isso, vamos definir este método na classe Comanda:

class Comanda
  def numero=(numero)
    @numero = numero
  end

  def fechar
  ...
end
Enter fullscreen mode Exit fullscreen mode

No corpo deste método, a variável @numero é conhecida como Variável de Instância e ela faz parte APENAS do escopo do objeto. É exatamente por este motivo que anteriormente eu disse que um atributo de um objeto nunca será manipulado diretamente fora dele, porque não existe outro recurso seguro para que isso seja feito além de um Método.

Estamos criando um método numero= (você não leu errado, ele tem um "=" no final do nome) e neste método estamos definindo que ele precisa receber um atributo numero. Dentro deste método, estamos pegando o valor que será enviado como parâmetro para numero e atribuindo em @numero.

Da mesma forma, podemos criar um método para acessar o valor do atributo @numero. Com isso, criamos mais um método na Comanda:

class Comanda
  def numero=(numero)
  ...

  def numero
    @numero
  end

  ...
end

...
Enter fullscreen mode Exit fullscreen mode

No Ruby, apesar da palavra-chave return existir, nós a omitimos em diversos casos porque o Ruby sempre retorna a última expressão de um método

Neste método numero (que é diferente do método numero=), nós estamos retornando o valor do atributo @numero.

Para utilizarmos estes dois métodos, não será muito diferente do método fechar que usamos na sessão anterior. Podemos chamá-los desta forma:

class Comanda
  ...
end

minha_comanda = Comanda.new
minha_comanda.numero = 5421
puts minha_comanda.numero
puts minha_comanda.fechar
Enter fullscreen mode Exit fullscreen mode

Neste caso, estamos chamando o método numero= passando como valor 5142 e em seguida chamamos o método numero imprimindo o que ele retornou. Por incrível que pareça, o Ruby nos deixa criar um método com um "=" no final do seu nome e chamar desta forma. Esta chamada é a mesma coisa que fazer minha_comanda.numero=(5421)

Olhando o resultado deste puts da ultima linha, teremos impresso:

5142
Comanda fechada!
Enter fullscreen mode Exit fullscreen mode

Isso nos certifica que realmente o valor está sendo atribuído em @numero.

Para finalizar o papo desse post, vamos criar os mesmos métodos para o atributo atendente, mesa, itens. Os métodos para manipular e ler o número da mesa e os itens ficarão assim:

class Comanda
  def numero
  ...

  def atendente=(atendente)
    @atendente = atendente
  end

  def atendente
    @atendente
  end

  def mesa=(mesa)
    @mesa = mesa
  end

  def mesa
    @mesa
  end

  def itens=(itens)
    @itens= itens
  end

  def itens
    @itens
  end

  ...
end

...
Enter fullscreen mode Exit fullscreen mode

Temos um novo método atendente= (com "=") para atribuir o nome da pessoa atendente e atendente (sem "=") para retornar o valor, que no caso está atribuído na variável de instância @atendente. O mesmo está ocorrendo com a mesa e os itens.

Vamos utilizar estes métodos para atribuir valores e imprimi-los. Ficaremos com o código do desta forma:

class Comanda
  ...
end

minha_comanda = Comanda.new
minha_comanda.numero = 5421
minha_comanda.atendente = 'Maria'
minha_comanda.mesa = 17
minha_comanda.itens = ['Café pingado', 'Pão de queijo']
puts "Número: #{minha_comanda.numero} | Atendente: #{minha_comanda.atendente} | Mesa: #{minha_comanda.mesa} | Itens: #{minha_comanda.itens.join(',')}"
Enter fullscreen mode Exit fullscreen mode

Com isso, estamos atribuindo 5142 no atributo @numero, "Maria" no atributo @atendente, 17 para @mesa e ['Café pingado', 'Pão de queijo'] para @itens

Executando este script, será impresso na tela:

Número: 5142 | Atendente: Maria | Mesa: 17 | Itens: Café pingado,Pão de queijo
Enter fullscreen mode Exit fullscreen mode

Com isso a gente termina essa segunda parte dessa série. Ainda tem mais, estamos no começo.

O código que foi feito aqui está neste repositório na branch parte_02:
https://github.com/dfmoreto/dev_to-poo_ruby/tree/parte_02

Curtiu? Sinta-se à vontade para fazer correções, comentários ou acréscimos ali em baixo nos comentários =)

Top comments (1)

Collapse
 
rochaisadora profile image
Isadora Rocha

Minha nossa, primo!!! Que post incrível!! Esclareceu 50% das minhas dúvidas! Vim de Java para Ruby e sempre acho que as coisas são mais complexas kkkkkk

Obrigadão! Posta mais sempre que puder, por favor!