连接检查

连接检查会限制哪些连接(以及相应的块)可以相互连接。

连接检查对建模类型很有用。例如,以下三个代码块没有任何关联,因为它们代表返回不同类型的代码:

一个空列表块,连接到一个平方根块,连接到一个转换为大写的块

连接检查可用于阻止这些分块连接。这样可以为用户提供即时反馈,并避免许多简单的错误。

运作方式

每个连接都可以与“连接检查”相关联,后者是一个可为 null 的字符串数组。

两个连接可以连接,前提是:

  1. 它们是兼容的类型(例如,输出端连接到输入端)。
  2. 它们的连接检查中至少有一个字符串是相同的。

例如,以下两个检查的连接可以关联,因为它们共享 'apple' 字符串:

['apple', 'ball', 'cat']
['apple', 'bear', 'caterpillar']

但是,这两个检查之间无法建立关联,因为它们没有共享任何字符串:

['apple', 'ball', 'cat']
['ape', 'bear', 'caterpillar']

还有一个特殊情况。如果任一数组为 null,则这两个连接也可以连接。这样,您就可以定义可连接到任何内容的连接。

null
['ape', 'bear', 'caterpillar]

示例

如需查看有关如何使用连接检查的示例列表,请参阅连接检查手册

设置检查

默认情况下,所有连接都有 null 连接检查,这意味着它们可以连接到任何内容。连接检查需要手动分配。

向连接分配连接检查的方式因您使用的是 JSON 代码块定义还是 JavaScript 代码块定义而异。

JSON

对于顶级连接,您可以直接将检查分配给定义连接的属性。您分配的值可以是 null、字符串(将成为连接检查中的唯一条目)或字符串数组。

{
  'type': 'custom_value_block',

  'output': 'a connection check entry',
},
{
  'type': 'custom_statement_block',

  'nextStatement': null, // null check
  'previousStatement': ['four', 'connection', 'check', 'entries']
}

对于输入,您可以将检查分配给输入定义的 check 属性。如果 check 属性不存在,则检查结果被视为 null。您分配的值可以是字符串,也可以是字符串数组。

{
  'type': 'custom_block',
  'message0': '%1 %2',

  'args0': [
    {
      'type': 'input_value',
      'check': 'a connection check entry' // Accepts custom_value_block
    },
    {
      'type': 'input_statement',
      'check': ['two', 'entries'] // Accepts custom_statement_block
    }
  ]
}

JavaScript

对于顶级连接,您可以直接将检查传递给用于定义连接的方法。如果您未传递值,系统会将检查视为 null。您传递的值可以是字符串(这将成为连接检查中的唯一条目),也可以是字符串数组。

Blockly.Blocks['custom_value_block'] = {
  init: function() {
    this.setOutput(true, 'a connection check entry');
  }
};
Blockly.Blocks['custom_statement_block'] = {
  init: function() {
    this.setNextStatement(true); // null check
    this.setPreviousStatement(true, ['four', 'connection', 'check', 'entries']);
  }
};

对于输入,您可以在定义输入后将检查传递给 setCheck 方法。如果未调用 setCheck 方法,则检查将被视为 null。您传递的值可以是字符串,也可以是字符串数组。

Blockly.Blocks['custom_block'] = {
  init: function() {
    this.appendValueInput('NAME')
        .setCheck('a connection check entry'); // Accepts custom_value_block
    this.appendStatementInput('NAME')
        .setCheck(['two', 'entries']); // Accepts custom_statement_block
  }
};

内置检查字符串

内置块具有值为 'Array''Boolean''Colour''Number''String' 的连接检查。如果您希望自己的块与内置块互操作,可以使用这些值使其兼容。

限制

此系统非常稳健,可以解决许多用例,但也有一些限制。

限制更广泛的上下文

此系统本身不支持限制允许连接的“更大情境”。例如,您不能说 break 块只能存在于 loop 块内。连接检查系统仅考虑连接的直接两个连接。

可以通过使用事件系统监听块移动事件并检查块是否放置不当来支持此功能。

Blockly.Blocks['custom_block'] = {
  init: function() { }

  onchange: function(e) {
    if (this.workspace.isDragging()) return;
    if (e.type !== Blockly.Events.BlockMove) return;
    if (!this.getSurroundLoop()) this.outputConnection.disconnect();
  }

  loopTypes: new Set(); // Your valid *block types* (not connection checks).

  getSurroundLoop: function () {
    let block = this.getSurroundParent();
    do {
      if (loopTypes.has(block.type)) return block;
      block = block.getSurroundParent();
    } while (block);
    return null;
  },
}

泛型类型

此系统本身不支持定义泛型。例如,您无法创建会“返回”其输入的“Identity”块。

您可以通过主动更改块输出的连接检查以匹配其输入,在一定程度上支持此功能。您可以使用事件系统监听块移动事件来实现此目的。

Blockly.Blocks['custom_block'] = {
  init: function() { }

  onchange: function(e) {
    if (e.type !== Blockly.Events.BlockMove) return;
    this.setOutput(
        true, this.getInputTargetBlock()?.outputConnection.getCheck());
  }
}

但是,如果关联的块也是通用块,则此方法无法正常运行。目前没有针对此问题的有效解决方法。

连接检查器

如果此系统不适用于您的用例,您还可以通过创建自定义连接检查器来更改连接检查的比较方式。

例如,如果您想创建一个更高级的系统来处理此系统的一些限制,可以创建自定义连接检查器。