Переменные

Переменные — важная концепция программирования. 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);
    ...
  }
};

Это создает следующие два блока:

Блоки получения и установки для переменной `foo`.

Важно отметить, что, установив «выход» метода получения переменной равным 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 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);
    ...
  }
};

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

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

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

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

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

Открытая категория «Переменные» с кнопкой «Создать переменную».

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

Та же категория после создания переменных `foo` и `bar`. Она содержит кнопку «Создать переменную», блоки set-variable-to и change-variable-by, а также блоки getter.

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

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

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

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

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

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

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

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

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