As verificações de conexão restringem quais conexões (e, portanto, blocos) podem se conectar umas às outras.
As verificações de conexão são úteis para tipos de modelagem. Por exemplo, os três blocos a seguir não têm negócios sendo conectados, porque representam um código que retorna tipos diferentes:
As verificações de conexão podem ser usadas para evitar que esses blocos se conectem. Isso oferece aos usuários feedback instantâneo e evita muitos erros simples.
Como funcionam
Toda conexão pode ser associada a uma "verificação de conexão", que é uma matriz anulável de strings.
Duas conexões podem se conectar se:
- Eles são tipos compatíveis (por exemplo, uma saída conectada a uma entrada).
- Elas têm pelo menos uma string em comum na verificação de conexão.
Por exemplo, as duas verificações a seguir podem se conectar porque compartilham a string 'apple'
:
['apple', 'ball', 'cat']
['apple', 'bear', 'caterpillar']
No entanto, não foi possível realizar estas duas verificações porque elas não compartilham strings:
['apple', 'ball', 'cat']
['ape', 'bear', 'caterpillar']
Existe outro caso especial. Se uma das matrizes for null
, as duas
conexões também poderão se conectar. Isso permite definir conexões
que podem se conectar a qualquer coisa.
null
['ape', 'bear', 'caterpillar]
Definir verificações
Por padrão, todas as conexões têm uma verificação de conexão null
, o que significa que podem
se conectar a qualquer coisa. Verificações de conexão precisam ser atribuídas manualmente.
A maneira de atribuir verificações de conexão às conexões é diferente, dependendo do uso de definições de bloco JSON ou JavaScript.
JSON
Para conexões de nível superior, você atribui a verificação diretamente à propriedade que define a conexão. O valor atribuído pode ser null
, uma string (que
se torna a única entrada na verificação de conexão) ou uma matriz de strings.
{
'type': 'custom_block',
'output': null,
'nextStatement': 'a connection check entry',
'previousStatement': ['four', 'connection', 'check', 'entries']
}
Para entradas, você pode atribuir a verificação a uma propriedade check
da definição de entrada. Se a propriedade check
não existir, a verificação será considerada null
. O valor atribuído pode ser uma string ou uma matriz de strings.
{
'type': 'custom_block',
'message0': '%1 %2',
'args0': [
{
'type': 'input_value',
'check': 'a connection check entry'
},
{
'type': 'input_statement',
'check': ['four', 'connection', 'check', 'entries']
}
]
}
JavaScript
Para conexões de nível superior, você pode passar a verificação diretamente para o método que define a conexão. Se você não passar um valor, a verificação será considerada
null
. O valor transmitido pode ser uma string (que se torna a única entrada na
verificação de conexão) ou uma matriz de strings.
Blockly.Blocks['custom_block'] = {
init: function() {
this.setOutput(true); // null check
this.setNextStatement(true, 'a connection check entry');
this.setPreviousStatement(true, ['four', 'connection', 'check', 'entries']);
}
}
Para entradas, é possível passar a verificação para o método setCheck
, depois de
definir a entrada. Se o método setCheck
não for chamado, a verificação será
considerada null
. O valor transmitido pode ser uma string ou uma matriz de strings.
Blockly.Blocks['custom_block'] = {
init: function() {
this.appendValueInput('NAME')
.setCheck('a connection check entry');
this.appendStatementInput('NAME')
.setCheck(['four', 'connection', 'check', 'entries']);
}
}
Strings de verificação integradas
Os blocos integrados têm verificações de conexão com os valores 'Array'
,
'Boolean'
, 'Colour'
, 'Number'
e 'String'
. Se você quiser que seus blocos interoperem com os blocos integrados, use esses valores para torná-los compatíveis.
Exemplos de valor
Ao definir verificações de conexão para entradas e saídas, geralmente você precisa pensar que elas representam tipos.
As verificações de entradas precisam incluir todos os "tipos" que aceitam, e as verificações de saídas precisam incluir exatamente o que "retornam".
Aceitar um único tipo
No caso mais básico, em que você quer criar um bloco que "aceite" ou "retorne" um tipo, é necessário incluir esse tipo na verificação de conexão da conexão.
Aceitar vários tipos
Para criar um bloco que "aceite" vários tipos, você precisa incluir todos os tipos aceitos na verificação de conexão da entrada.
Por convenção, se uma saída às vezes puder ser aceita em várias situações (por exemplo, se você permitir que números às vezes sejam usados como strings), a saída precisará ser mais restritiva, e as entradas precisam ser mais permissivas. Essa convenção garante que as saídas não se conectem onde não forem compatíveis.
Aceita qualquer tipo
Para criar um bloco que "aceite" qualquer tipo, defina a verificação de conexão
da entrada como null
.
Subtipos de retorno
Para criar um bloco que "retorne" um subtipo, é necessário incluir o tipo e o supertipo na verificação de conexão da saída.
No caso de subtipos, não há problema em ter várias verificações em uma verificação de saída, porque o bloco sempre "retorna" os dois tipos.
Retornar tipos parametrizados
Para criar um bloco que "retorne" um tipo parametrizado, é necessário incluir a versão parametrizada e a não parametrizada na verificação de conexão da saída.
Dependendo do nível de rigor da linguagem de blocos que você quer, também é possível incluir as variações do tipo.
Assim como com os subtipos, não há problema em ter várias verificações em uma verificação de saída nesse caso, porque o bloco sempre "retorna" os dois tipos.
Exemplos de pilha ou instrução
Existem algumas maneiras comuns de os desenvolvedores definirem verificações de conexões anteriores e próximas. Normalmente, você pensa nisso como uma restrição da ordem dos blocos.
As próximas conexões precisam incluir quais blocos precisam seguir o atual, e as conexões anteriores incluem o que o bloco atual "é".
Manter os blocos em ordem
Para criar um conjunto de blocos que se conectam em uma ordem definida, é necessário incluir quais blocos precisam seguir o atual na próxima verificação de conexão e qual bloco atual "está" na verificação de conexão anterior.
Permitir muitos blocos intermediários
Para criar um conjunto de blocos ordenados que permitam muitos blocos intermediários, é necessário incluir pelo menos uma entrada da verificação de conexão anterior do bloco do meio na próxima verificação de conexão do bloco do meio. Isso permite que o bloco seja seguido por mais de si mesmo.
Não permitir blocos intermediários
Para criar um conjunto de blocos ordenados em que os blocos intermediários são opcionais, você precisa incluir pelo menos uma entrada da verificação de conexão anterior do bloco do meio e da verificação de conexão anterior do último bloco na próxima verificação de conexão do primeiro bloco. Isso permite que o primeiro bloco seja seguido por um bloco do meio ou um último.
Pilhas
Para criar um bloco que só possa ser seguido por blocos de um grupo ou de outro (e não de ambos), você precisa fazer duas coisas:
É necessário incluir pelo menos uma entrada das duas verificações de conexão anteriores dos grupos na próxima verificação de conexão do primeiro bloco.
Você precisa definir as próximas verificações de conexão dos grupos para incluir apenas valores que estão nas verificações de conexão anteriores, para que só possam ser seguidos por blocos do mesmo grupo.
Limitações
Esse sistema é bastante robusto e pode resolver muitos casos de uso, mas tem algumas limitações.
Restringir o contexto maior
Esse sistema, por si só, não é compatível com a restrição do "contexto maior" em
que uma conexão pode se conectar. Por exemplo, não é possível dizer que um
bloco break
só pode existir dentro de um bloco loop
. O sistema de
verificação de conexão considera apenas as duas conexões imediatas que estão sendo conectadas.
Você pode fazer isso usando o sistema de eventos para detectar eventos block move e verificar se o bloco está posicionado incorretamente.
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;
},
}
Tipos genéricos
Esse sistema, por si só, não é compatível com a definição de tipos genéricos. Por exemplo, não é possível criar um bloco "Identity", que "retorna" qualquer que seja a entrada.
Você pode oferecer suporte de alguma forma alterando ativamente a verificação de conexão na saída do bloco para corresponder à entrada. Isso pode ser feito usando o sistema de eventos para detectar bloqueios de eventos de movimento.
Blockly.Blocks['custom_block'] = {
init: function() { }
onchange: function(e) {
if (e.type !== Blockly.Events.BlockMove) return;
this.setOutput(
true, this.getInputTargetBlock()?.outputConnection.getCheck());
}
}
No entanto, se o bloco conectado também for genérico, isso não vai funcionar corretamente. Não há uma boa solução para esse caso.
Verificadores de conexão
Se esse sistema não funcionar no seu caso de uso, também será possível alterar a forma como as verificações de conexão são comparadas criando um verificador de conexão personalizado.
Por exemplo, se você quiser criar um sistema mais avançado que gerencie algumas das limitações deste, crie um verificador de conexão personalizado.