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
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
Com o
Comanda.new
criamos um objeto Comanda e armazenamos na variávelminha_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
...
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
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!
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
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
...
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
Neste caso, estamos chamando o método
numero=
passando como valor5142
e em seguida chamamos o métodonumero
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 fazerminha_comanda.numero=(5421)
Olhando o resultado deste puts
da ultima linha, teremos impresso:
5142
Comanda fechada!
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
...
Temos um novo método
atendente=
(com "=") para atribuir o nome da pessoa atendente eatendente
(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(',')}"
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
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)
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!