As variáveis são um conceito importante de programação. O Blockly é compatível com linguagens de tipagem dinâmica, como Python e JavaScript. Com um pouco mais de trabalho, é possível adicionar informações para oferecer suporte a linguagens de tipagem forte (ou estática), como Java ou C.
Para mais informações sobre linguagens dinâmicas e estáticas, consulte Introdução aos tipos de dados: estáticos, dinâmicos, fortes e fracos.
O Blockly fornece campos de variáveis, que são caixas de combinação dinâmicas que mostram os nomes das variáveis fornecidas pelo usuário. Confira um exemplo abaixo.
Por padrão, o Blockly permite que qualquer tipo seja atribuído a uma variável, e todos os geradores fornecidos pelo Blockly são para linguagens com tipagem dinâmica. Se você estiver usando uma linguagem digitada, configure o Blockly para oferecer suporte a ela fazendo o seguinte:
- Especifique um tipo de variável e os blocos dela, incluindo getters e setters.
- Configure a caixa de ferramentas para usar seu tipo de variável e blocos.
- Defina geradores para variáveis e blocos.
Blocos de variáveis sem tipo
Os blocos mais básicos para acessar e manipular uma variável são os blocos getter e setter. Vamos analisar os blocos getter e setter fornecidos pelo Blockly.
JSON
// Block for variable getter.
{
"type": "variables_get",
"message0": "%1",
"args0": [
{ // Beginning of the field variable dropdown
"type": "field_variable",
"name": "VAR", // Static name of the field
"variable": "%{BKY_VARIABLES_DEFAULT_NAME}" // Given at runtime
} // End of the field variable dropdown
],
"output": null, // Null means the return value can be of any type
...
},
// Block for variable setter.
{
"type": "variables_set",
"message0": "%{BKY_VARIABLES_SET}",
"args0": [
{
"type": "field_variable",
"name": "VAR",
"variable": "%{BKY_VARIABLES_DEFAULT_NAME}"
},
{
"type": "input_value", // This expects an input of any type
"name": "VALUE"
}
],
...
}
JavaScript
// Block for variable getter.
Blockly.Blocks['variables_get'] = {
init: function() {
this.appendDummyInput()
.appendField(new Blockly.FieldVariable("VAR_NAME"), "FIELD_NAME");
this.setOutput(true, null);
...
}
};
// Block for variable setter.
Blockly.Blocks['variables_set'] = {
init: function() {
this.appendValueInput("NAME")
.setCheck(null)
.appendField("set")
.appendField(new Blockly.FieldVariable("VAR_NAME"), "FIELD_NAME")
.appendField("to");
this.setOutput(true, null);
...
}
};
Isso cria os dois blocos a seguir:
Um detalhe importante é que, ao definir a "saída" do getter de variável como nula, o valor de retorno pode ser de qualquer tipo. Além disso, observe que a entrada do setter de variável não especifica nenhuma verificação. Como resultado, a variável pode ser definida para qualquer tipo de valor.
Blocos de variáveis tipadas
É possível adicionar getters e setters que aplicam a verificação de tipo. Por exemplo, se você
criou uma variável do tipo "Panda"
, as definições a seguir criam um
getter e um setter com os tipos apropriados.
JSON
// Block for Panda variable getter.
{
"type": "variables_get_panda",
"message0": "%1",
"args0": [
{
"type": "field_variable",
"name": "VAR",
"variable": "%{BKY_VARIABLES_DEFAULT_NAME}",
"variableTypes": ["Panda"], // Specifies what types to put in the dropdown
"defaultType": "Panda"
}
],
"output": "Panda", // Returns a value of "Panda"
...
},
// Block for Panda variable setter.
{
"type": "variables_set_panda",
"message0": "%{BKY_VARIABLES_SET}",
"args0": [
{
"type": "field_variable",
"name": "VAR",
"variable": "%{BKY_VARIABLES_DEFAULT_NAME}",
"variableTypes": ["Panda"],
"defaultType": "Panda"
},
{
"type": "input_value",
"name": "VALUE",
"check": "Panda" // Checks that the input value is of type "Panda"
}
],
"previousStatement": null,
"nextStatement": null,
...
}
JavaScript
// Block for Panda variable getter.
Blockly.Blocks['variables_get_panda'] = {
init: function() {
this.appendDummyInput()
.appendField(new Blockly.FieldVariable(
"VAR_NAME", ['Panda'], 'Panda'), "FIELD_NAME");
this.setOutput(true, 'Panda');
...
}
};
// Block for Panda variable setter.
Blockly.Blocks['variables_set_panda'] = {
init: function() {
this.appendValueInput("NAME")
.setCheck('Panda')
.appendField("set")
.appendField(new Blockly.FieldVariable(
"VAR_NAME", null, ['Panda'], 'Panda'), "FIELD_NAME")
.appendField("to");
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
...
}
};
Isso cria dois tipos de blocos: um getter e um setter. Os menus suspensos mostram apenas variáveis do tipo "Panda"
. As entradas e saídas deles só aceitam
conexões do tipo "Panda"
. O defaultType
do campo precisa ser definido como um dos valores na matriz variableTypes
. Não definir o defaultType
ao fornecer uma matriz variableTypes
vai gerar um erro.
Por padrão, não há um indicador visual para informar ao usuário qual tipo está sendo usado. Uma maneira fácil de diferenciar os tipos de variáveis é por cor.
Adicionar variáveis à caixa de ferramentas
Para que esse novo tipo de variável seja útil para seus usuários, adicione uma maneira de criar e usar as novas variáveis.
Crie uma categoria dinâmica para variáveis se você ainda não tiver uma.
Adicione os novos getters e setters à categoria.
Botão "Criar variável"
Em seguida, o usuário precisa de uma maneira de criar variáveis. A maneira mais simples é com um botão "Criar variável".
Ao criar o botão, faça a chamada de callback
Blockly.Variables.createVariableButtonHandler(button.getTargetWorkspace(), null, 'panda');
e uma variável tipada "Panda"
será criada.
A maneira mais fácil de permitir que os usuários criem variáveis de vários tipos é ter um botão "criar" por tipo (por exemplo, "Criar variável de string", "Criar variável numérica", "Criar variável Panda").
Se você tiver mais de dois ou três tipos de variáveis, poderá acabar com muitos botões. Nesse caso, use @blockly/plugin-typed-variable-modal para mostrar um pop-up em que os usuários podem selecionar o tipo de variável desejado.
Definir geradores
Por fim, você precisará definir geradores de código de bloco para os novos blocos de variáveis. Você também pode acessar a lista de variáveis diretamente
com Workspace.getVariableMap().getAllVariables()
para receber todas as variáveis de todos os
tipos ou Workspace.getVariableMap().getVariablesOfType()
para receber todas as variáveis
de um tipo específico.