Utilização de módulos em cristal

Conforme sua aplicação cresce, você gostaria de passar de um grande arquivo .cr para separar seu código em arquivos menores.

Você pode usar o requerimento do seu arquivo .cr principal para adicionar código de outros arquivos:

requerem "./ferramentas/*".

Esta declaração adicionará o código do diretório de ferramentas, relativo ao seu arquivo .cr principal.

Isso ajudará a separar sua aplicação "fisicamente", mas também pode ser desejável separá-la logicamente - talvez parte do código possa ser reutilizado em outros projetos, e talvez você também queira evitar colisões de namespace.

O que é uma colisão de namespace?

Se um método ou nome de classe, ou nome constante for usado duas vezes em arquivos de origem diferentes no namespace global, você terá uma colisão.

Como é que o compilador deve saber, que método/classe quer realmente dos dois que estão definidos?

Para evitar colisões de namespace você separa seu código em módulos.

por exemplo:

módulo Debug

   classe Classe de Amostra

   final

   SAMPLE_CONSTANT = "algum valor".

   macro samplemacro(some_variable)

     #algum código macro

   final

1TP3O seu código vai para aqui

final

Código de acesso em módulos

Agora você pode acessar o código (depois de ter requerido o arquivo em que o módulo está definido) desta forma:

sampleinstance = Debug::SampleClass.new()

p Debug::SAMPLE_CONSTANT

Debug.samplemacro

Note que uma macro é chamada com uma sintaxe ".", não com uma sintaxe ":". Você pode considerá-la como um método do Módulo.

Incluindo módulos

Se, por outro lado, você achar a notação adicional cansativa, você pode incluir o módulo usando o nome do método assim:

incluem Debug

então você poderá acessar os métodos, classes, constantes e macros sem qualquer notação adicional - como se o código fosse literalmente copiado e colado em seu outro arquivo fonte:

sampleinstance = SampleClass.new()

p SAMPLE_CONSTANT

samplemacro