Sprawdzanie połączenia

Sprawdzanie połączeń ogranicza, które połączenia (a zatem bloki) mogą się ze sobą łączyć.

Sprawdzanie połączeń jest przydatne w przypadku typów modelowania. Na przykład te 3 bloki nie są ze sobą połączone, ponieważ reprezentują kod, który zwraca różne typy:

Puste pole listy połączone z polem pierwiastek kwadratowy, które jest połączone z polem wielka litera

Możesz użyć kontroli połączeń, aby uniemożliwić tym blokom nawiązywanie połączeń. Dzięki temu użytkownicy otrzymują natychmiastową informację zwrotną i nie popełniają wielu prostych błędów.

Jak działają

Każde połączenie może być powiązane z „sprawdzaniem połączenia”, które jest tablicą ciągów znaków z możliwością wartości null.

Dwa połączenia mogą się połączyć, jeśli:

  1. Są to typy, które są ze sobą zgodne (np. wyjście połączone z wejściem).
  2. Mają co najmniej 1 łańcuch znaków wspólny dla obu testów połączeń.

Na przykład połączenia z tymi 2 kontrolami mogą się połączyć, ponieważ mają wspólny ciąg znaków 'apple':

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

Połączenia z tymi dwoma elementami nie mogły się jednak utworzyć, ponieważ nie mają wspólnych ciągów znaków:

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

Jest jeszcze jeden szczególny przypadek. Jeśli dowolny z macierzy jest null, te 2 połączenia mogą się połączyć. Dzięki temu możesz zdefiniować połączenia, które mogą łączyć się z czymkolwiek.

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

Przykłady

Przykłady korzystania z sprawdzania połączeń znajdziesz w artykule Sprawdzanie połączeń – podręcznik.

Ustawianie kontroli

Domyślnie wszystkie połączenia mają ustawioną kontrolę połączenia null, co oznacza, że mogą łączyć się z czymkolwiek. Sprawdzanie połączeń musi być przypisane ręcznie.

Sposób przypisywania połączeń do połączeń jest inny w zależności od tego, czy używasz definicji bloków w formacie JSON, czy w formacie JavaScript.

JSON

W przypadku połączeń najwyższego poziomu możesz przypisać weryfikację bezpośrednio do usługi, która definiuje połączenie. Przypisaną wartością może być null, ciąg znaków (który staje się jedynym wpisem w sprawdzaniu połączenia) lub tablica ciągów znaków.

{
  'type': 'custom_value_block',

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

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

W przypadku danych wejściowych możesz przypisać sprawdzenie do właściwości check definicji danych wejściowych. Jeśli właściwość check nie istnieje, sprawdzanie jest traktowane jako null. Przypisana wartość może być ciągiem tekstowym lub tablicą ciągów tekstowych.

{
  '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

W przypadku połączeń najwyższego poziomu możesz przekazać kontrolę bezpośrednio metodzie definiującej połączenie. Jeśli nie podasz wartości, test zostanie uznany za null. Wartość, którą przekazujesz, może być ciągiem znaków (który staje się jedynym wpisem w sprawdzaniu połączenia) lub tablicą ciągów znaków.

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']);
  }
};

W przypadku danych wejściowych możesz przekazać sprawdzenie do metody setCheck po zdefiniowaniu danych wejściowych. Jeśli metoda setCheck nie zostanie wywołana, sprawdzenie zostanie uznane za null. Wartość, którą przekazujesz, może być ciągiem tekstowym lub tablicą ciągów tekstowych.

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

Wbudowane ciągi znaków sprawdzania

Wbudowane bloki mają sprawdzanie połączeń z wartościami 'Array', 'Boolean', 'Colour', 'Number''String'. Jeśli chcesz, aby Twoje bloki mogły współpracować z wbudowanymi blokami, możesz użyć tych wartości, aby zapewnić ich zgodność.

Ograniczenia

Ten system jest dość niezawodny i może rozwiązać wiele problemów, ale ma też kilka ograniczeń.

Ogranicz szerszy kontekst

Ten system sam w sobie nie obsługuje ograniczania „większego kontekstu”, w którym połączenie może się nawiązać. Nie możesz na przykład określić, że blok break może występować tylko w bloku loop. System sprawdzania połączeń bierze pod uwagę tylko 2 bezpośrednie połączenia.

Możesz to umożliwić, korzystając z systemu zdarzeń, aby odbierać zdarzenia przesunięcia bloku i sprawdzać, czy blok nie jest nieprawidłowo umieszczony.

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;
  },
}

Typy ogólne

Ten system sam w sobie nie obsługuje definiowania typów ogólnych. Nie możesz na przykład utworzyć bloku „Tożsamość”, który „zwraca” dowolny podany mu argument.

Możesz w pewnym stopniu to umożliwić, aktywnie zmieniając sprawdzanie połączenia w wyjściu bloku, aby pasowało do jego wejścia. Możesz to zrobić, korzystając z systemu zdarzeń do nasłuchiwania zdarzeń przenoszenia bloku.

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

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

Jeśli jednak połączony blok jest także ogólny, nie będzie działać prawidłowo. W tym przypadku nie ma dobrego obejścia problemu.

Sprawdzanie połączeń

Jeśli ten system nie spełnia Twoich potrzeb, możesz zmienić sposób porównywania kontroli połączeń, tworząc niestandardowy sprawdzacz połączeń.

Jeśli na przykład chcesz utworzyć bardziej zaawansowany system, który obejmie niektóre ograniczenia tego systemu, możesz utworzyć niestandardowy sprawdzacz połączeń.