Os Módulos em Crystal têm dois propósitos:
O primeiro propósito é criar um namespace para evitar colisões de nomes. Além disso, ele também agrupa código, o que facilita entender para que o código serve.
O segundo propósito é definir mixins para compartilhar código entre tipos.
Módulos são parecidos com classes, mas a principal diferença é que não podem ser instanciados e, por isso, não têm variáveis de instância.
Para declarar um módulo, você usa a palavra-chave module seguida do nome do módulo.
module Foo
end
Um namespace é uma forma de agrupar código.
Isso evita colisões de nomes e facilita entender para que o código serve.
Quando você quer acessar uma constante ou uma classe que foi colocada dentro de um namespace, usa o operador ::.
module Foo
class Bar
end
end
Foo::Bar.new
Isso pode ser útil quando, por exemplo, várias classes precisam da mesma funcionalidade "básica", ou quando código precisa ser compartilhado entre classes sem relação. Ou quando você quer compartilhar código entre classes que não têm relação.
Há duas formas diferentes de usar um módulo como mixin: a primeira é usar a palavra-chave include, e a segunda é usar a palavra-chave extend.
Os dois métodos tornam as constantes disponíveis para o tipo que inclui ou estende o módulo.
O include deixa todos os métodos do módulo disponíveis como métodos de instância no tipo que inclui o módulo.
A palavra-chave include deve ficar no topo do tipo, seguida do nome do módulo.
module Foo
def foo
"foo"
end
end
class Bar
include Foo
end
Bar.new.foo # => "foo"
O extend funciona de forma parecida com o include, mas, em vez de deixar os métodos disponíveis como métodos de instância, deixa-os disponíveis como métodos de classe.
A palavra-chave extend deve ser escrita no topo do tipo, seguida do nome do módulo.
module Foo
def foo
"foo"
end
end
class Bar
extend Foo
end
Bar.foo # => "foo"
Um padrão típico em Crystal usa o padrão extend self em um módulo.
Isso deixa todos os métodos do módulo disponíveis como métodos de classe no próprio módulo.
Isso significa que você não precisa atribuir cada método ao módulo usando a sintaxe def self.method_name.
module Foo
extend self
def foo
"foo"
end
end
Foo.foo # => "foo"
A Bellebrook Basketball League é uma liga com vários times, cada um com um elenco de jogadores. Uma nova temporada está prestes a começar, e eles precisam criar um novo sistema de venda de ingressos para os jogos. Na temporada passada, eles vendiam ingressos na entrada do estádio, mas a popularidade explodiu, e eles decidiram vender ingressos online nesta temporada para lidar com o aumento da demanda.
A liga entrou em contato com você e pediu que você criasse um sistema para gerenciar a venda de ingressos.
Primeiro, você precisa criar um sistema de venda de ingressos para gerenciar a venda de ingressos. O sistema de venda de ingressos precisa informar quantos ingressos estão disponíveis para um jogo.
Uma instância de uma classe chamada TicketSystem deve ser criada para cada jogo.
O estado inicializado deve conter as seguintes informações:
Construa um estado inicializado a partir de argumentos que indiquem o número de ingressos disponíveis e em qual estádio a partida é disputada.
O estado inicializado deve ser composto pelas variáveis de instância @tickets_available e @stadium.
Elas devem conter o primeiro e o segundo argumentos fornecidos, respectivamente.
TicketSystem.new(100, "Bellebrook")
# => #<TicketSystem:0x10f0b8 @tickets_available=100, @stadium="Bellebrook">
Primeiro, você precisa criar um método que retorne a quantidade de ingressos disponíveis para um determinado jogo.
Defina um módulo chamado TicketingReservation acima da classe já definida.
Esse módulo deve ser incluído na classe TicketSystem.
Dentro do módulo, defina um método chamado tickets_available.
Esse método deve retornar a quantidade de ingressos disponíveis.
ticket_system = TicketSystem.new(100)
ticket_system.tickets_available
#=> 100
Você deve criar um método que verifique se há ingressos disponíveis para um determinado jogo. O jogo precisa ter 100 ingressos em reserva. Isso serve para garantir que sempre haja ingressos disponíveis para as pessoas que compram na entrada do estádio.
Dentro do módulo TicketingReservation, defina um método chamado order_ticket?.
O método deve retornar true se houver pelo menos 100 ingressos disponíveis e false caso contrário.
Se houver pelo menos 100 ingressos disponíveis, o método também deve diminuir em 1 o número de ingressos disponíveis.
ticket_system = TicketSystem.new(100)
ticket_system.order_ticket?
#=> true
O sistema de venda de ingressos precisa ter mensagens fáceis de entender para os usuários. E as mensagens devem parecer pessoais, então devem incluir o nome do usuário.
Se a compra do ingresso foi bem-sucedida, o usuário deve receber uma mensagem informando que a compra deu certo, o número do ingresso e em qual estádio o jogo é disputado. O número do ingresso deve ser o número de ingressos disponíveis antes do pedido.
Se a compra foi bem-sucedida, a mensagem deve ser assim: {name}, your purchase was successful, your ticket number is #{ticket_number}, and the game is played at the {stadium_name} stadium..
Se a compra não foi bem-sucedida, a mensagem deve ser assim: {name}, your purchase was unsuccessful, there are not enough tickets available..
Dentro do módulo TicketingReservation, defina um método chamado order_message que recebe um argumento name contendo o nome do comprador.
O método deve retornar uma string com a mensagem.
ticket_system = TicketSystem.new(100, "Bellebrook")
ticket_system.order_message("John")
#=> "John, your purchase was successful, your ticket number is #100, and the game is played at the Bellebrook stadium."
Crie sua conta no Exercism para aprender e dominar Crystal com 26 conceitos142 exercícios e mentoria humana de verdade, tudo de graça.