Переменные

Переменные — важная концепция программирования. Blockly поддерживает динамически типизированные языки, такие как Python и JavaScript, и, приложив немного дополнительных усилий, вы можете добавить информацию для поддержки строго типизированных языков (или статически типизированных языков), таких как Java или C.

Вот дополнительная информация о динамических и статических типизированных языках.

Blockly предоставляет поля переменных, которые представляют собой динамические раскрывающиеся списки, в которых отображаются имена переменных, предоставленных пользователем. Ниже приведен пример одного из них.

По умолчанию Blockly позволяет присваивать переменным любой тип, и все генераторы Blockly предназначены для динамически типизированных языков. Если вместо этого вы используете типизированный язык, вы можете настроить Blockly для его поддержки, выполнив следующие действия:

Нетипизированные блоки переменных

Самыми основными блоками для доступа к переменной и управления ею являются блоки получения и установки. Давайте пройдемся по блокам получения и установки, которые предоставляет 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);
    ...
  }
};

При этом создаются следующие два блока:

Важная деталь, на которую следует обратить внимание, заключается в том, что, установив для «выхода» метода получения переменной значение null, возвращаемое значение может быть любого типа. Также обратите внимание, что входные данные установщика переменных не содержат никаких проверок. В результате переменной можно присвоить любой тип значения.

Типизированные блоки переменных

Вы можете добавить геттеры и сеттеры, которые обеспечивают проверку типов. Например, если вы создали переменную типа «Panda», следующие определения создают методы получения и установки соответствующих типов.

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 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 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);
    ...
  }
};

При этом создаются два типа блоков: геттер и сеттер. В их раскрывающихся списках отображаются только переменные типа Panda. Их входы и выходы принимают только соединения типа Panda. В поле defaultType должно быть установлено одно из значений массива variableTypes . Если не задать defaultType при предоставлении variableTypes , возникнет ошибка.

По умолчанию визуальный индикатор, сообщающий пользователю, какой тип используется, отсутствует. Один из простых способов различать типы переменных — это цвет .

Добавить переменные на панель инструментов

Чтобы сделать этот новый тип переменных полезным для ваших пользователей, вам необходимо добавить способ создания и использования новых переменных.

Создайте новую динамическую категорию для переменных, если у вас ее еще нет.

Добавьте в категорию новые геттеры и сеттеры.

Кнопка «Создать переменную»

Далее вашему пользователю нужен способ создания переменных. Самый простой способ — с помощью кнопки «Создать переменную».

При создании кнопки сделайте обратный вызов

Blockly.Variables.createVariableButtonHandler(button.getTargetWorkspace(), null, 'panda');

и будет создана переменная типа Panda!

Самый простой способ разрешить пользователям создавать переменные нескольких типов — это иметь одну кнопку «Создать» для каждого типа (например, «Создать строковую переменную», «Создать числовую переменную», «Создать переменную Panda»).

Если у вас более двух или трех типов переменных, вы можете быстро получить слишком много кнопок. В этом случае рассмотрите возможность использования @blockly/plugin-typed-variable-modal для отображения всплывающего окна, из которого пользователи могут выбрать желаемый тип переменной.

Определить генераторы

Наконец, вам нужно будет определить генераторы блочного кода для ваших новых блоков переменных. Вы также можете получить доступ к списку переменных напрямую с помощью Blockly.Workspace.getAllVariables(), чтобы получить все переменные всех типов, или Blockly.Workspace.getVariablesOfType(), чтобы получить все переменные определенного типа.