As classes são um conceito central na programação orientada a objetos. No Crystal, tudo é um objeto, todo objeto tem um tipo e pode responder a alguns métodos. As classes são moldes para criar objetos, fornecendo valores iniciais para o estado, como variáveis, e implementações de comportamento, como métodos. Os objetos são instâncias de classe que guardam todas as variáveis de instância e estados.
Uma classe é definida com a palavra-chave class, seguida do nome da classe escrito em UpperCamelCase.
class Account
end
Para criar uma instância de uma classe, chame o nome da classe usando o método new.
class Account
end
account = Account.new
No exemplo acima, a variável account é uma instância da classe Account.
Ao criar uma instância, um método especial chamado initialize funciona como construtor.
Ele é chamado quando uma instância é criada.
O construtor permite definir o estado inicial da instância.
O método initialize pode receber argumentos, que são passados ao criar uma instância.
class Account
def initialize(number)
5 + number # => 9
end
end
Account.new(4)
O método initialize não pode retornar um valor manualmente; em vez disso, new retorna a instância recém-criada.
class Account
def initialize(number)
5 + number
end
end
Account.new(4)
# => #<Account:0x7f5dc33dcea0>
Um método de instância é um método disponível para uma instância de uma classe e que pode ser chamado nessa instância.
Os métodos de instância são definidos com a palavra-chave def, seguida do nome do método.
Eles são definidos dentro da definição da classe.
class Account
def balance
100
end
end
account = Account.new
account.balance # => 100
Variáveis de instância são variáveis disponíveis em todos os métodos da instância.
Para acessar uma variável de instância, você precisa definir um método de instância.
Elas podem ser inicializadas no método initialize.
São definidas com o prefixo @.
class Account
def initialize
@balance = 100
end
def balance
@balance
end
end
account = Account.new
account.balance
# => 100
Variáveis de instância também podem ser definidas dentro da definição da classe.
class Account
@age = 0
end
Variáveis de instância podem ser inicializadas com um argumento passado ao método initialize.
Como o Crystal não consegue inferir o tipo do argumento usado na inicialização, é preciso especificá-lo.
Se você quiser ler mais sobre isso, pode ler: inferência de tipos.
Para especificar o tipo da variável, você pode usar o símbolo :, seguido do tipo.
Por exemplo, se você quiser criar uma variável de instância chamada balance do tipo Int32, você pode fazer assim: @balance : Int32.
Ou, se você quiser criar uma variável de instância chamada raining do tipo Bool, você pode fazer assim: @raining : Bool.
Há algumas formas de fazer isso: declarar o argumento com o tipo no método initialize e depois atribuir o argumento à variável de instância, como no exemplo a seguir:
class Account
def initialize(balance : Int32)
@balance = balance
end
def balance
@balance
end
end
account = Account.new(1)
account_2 = Account.new(5)
account.balance
# => 1
account_2.balance
# => 5
Outra forma é declarar o tipo da variável de instância na definição da classe no formato @<variable> : <Type>, como no exemplo a seguir:
class Weather
@raining : Bool
def initialize(raining)
@raining = raining
end
def raining
@raining
end
end
weather = Weather.new(true)
weather.raining
# => true
Os métodos podem modificar variáveis de instância. Esses métodos podem ser chamados na instância da classe. Quando um método modifica uma variável de instância, essa mudança só fica disponível na instância da classe em que você o chamou.
class Account
def initialize(balance : Int32)
@balance = balance
end
def withdraw(amount)
@balance -= amount
end
def balance
@balance
end
end
account = Account.new(10)
account_2 = Account.new(10)
account.balance
# => 10
account_2.balance
# => 10
account.withdraw(5)
account.balance
# => 5
account_2.balance
# => 10
Métodos de classe são métodos definidos para uma classe, mas não para as suas instâncias.
Eles oferecem uma forma de criar métodos que não dependem do estado da instância.
São definidos com a palavra-chave def, seguida de self.<method name>.
self é uma referência ao namespace a partir do qual self está sendo chamado.
Neste caso, refere-se à classe, Account.
Seria o mesmo que escrever Account., mas self. é a forma preferida.
class Account
def self.balance
100
end
end
Account.balance
# => 100
Seu amigo Johannes adora montar projetos de hardware do tipo "faça você mesmo" (DIY). Ele acabou de construir uma máquina de suco e está muito empolgado com isso. O objetivo de Johannes é conseguir preparar suco fresco todas as manhãs.
A máquina de suco de Johannes tem vários recursos sofisticados. Como um sistema de medição embutido, que mostra quanto suco há no copo. Também tem um temporizador, que indica há quanto tempo a máquina está funcionando.
Johannes não é o melhor em programação, mas quer criar um programa para controlar a máquina. Por isso, pediu sua ajuda.
A máquina tem uma luz de depuração. É um mecanismo simples: se a máquina estiver ligada na tomada, a luz de depuração acende. O programa só roda se a luz de depuração estiver acesa.
Este método deve ser um método de classe chamado JuiceMaker.
Defina o método de classe JuiceMaker.debug_light_on? que retorna true.
JuiceMaker.debug_light_on?
#=> true
Quando a máquina for ligada, ela deve criar uma instância de uma classe chamada JuiceMaker.
A máquina deve ter um estado inicializado.
O estado inicializado deve conter as seguintes informações:
false quando a máquina é ligada.Defina o estado inicializado, que recebe a quantidade de suco no copo como parâmetro, e construa o estado inicializado.
O estado inicializado deve conter uma variável de instância @running, definida como false, e uma variável de instância @fluid, baseada em um argumento passado quando a classe é inicializada.
JuiceMaker.new(5)
#=> #<JuiceMaker:0x10f0b8 @running=false, @fluid=5>
A máquina pode ser ligada e desligada.
Você precisa definir um método para ligar a máquina.
Quando a máquina é ligada, o estado de funcionamento deve ser definido como true.
Defina o método JuiceMaker#start, que liga a máquina.
juice_maker = JuiceMaker.new(5)
juice_maker.start
juice_maker
#=> #<JuiceMaker:0x10f0b8 @running=true, @fluid=5>
A máquina precisa conseguir informar o status dela.
Deve retornar true se a máquina estiver funcionando e false se não estiver.
Defina o método JuiceMaker#running?, que retorna o status da máquina.
juice_maker = JuiceMaker.new(5)
juice_maker.start
juice_maker.running?
#=> true
A máquina pode adicionar suco ao copo. A máquina consegue dizer quanto suco foi adicionado ao copo. A máquina precisa de ajuda para saber quanto suco há no copo depois que o suco é adicionado.
Defina o método JuiceMaker#add_fluid, que recebe a quantidade de suco adicionada como parâmetro e atualiza a quantidade de suco no copo.
juice_maker = JuiceMaker.new(5)
juice_maker.add_fluid(5)
juice_maker
#=> #<JuiceMaker:0x10f0b8 @running=false, @fluid=10>
A máquina pode ser ligada e desligada.
Você precisa definir um método para desligar a máquina.
Esse método só será chamado quando a máquina estiver funcionando.
Quando a máquina é desligada, o estado de funcionamento deve ser definido como false.
A máquina também precisa de ajuda para determinar quanto suco há no copo depois de ser desligada.
A máquina usa cinco unidades de suco por minuto.
Defina o método JuiceMaker#stop, que recebe o número de minutos que a máquina ficou funcionando como parâmetro e retorna a quantidade de suco no copo depois que a máquina foi desligada.
juice_maker = JuiceMaker.new(5)
juice_maker.start
juice_maker
#=> <JuiceMaker:0x10f0b8 @running=true, @fluid=5>
juice_maker.stop(1)
#=> #<JuiceMaker:0x10f0b8 @running=false, @fluid=0>
Crie sua conta no Exercism para aprender e dominar Crystal com 26 conceitos142 exercícios e mentoria humana de verdade, tudo de graça.