Mengubah definisi blok

Pertanyaan umum adalah cara mengubah definisi blok yang ada. Misalnya, Anda mungkin ingin menambahkan pemeriksaan koneksi atau mengubah kolom menjadi input nilai.

Secara umum, definisi blok tidak dapat diubah di tempat.

Cara mengubah definisi yang ada

Jika Anda ingin mengubah definisi jenis blok yang ada:

  1. Buat salinan definisi yang ada, termasuk generator kode blok.
  2. Ubah salinan dan beri nama baru untuk jenis Anda.
  3. Tambahkan definisi baru Anda ke Blockly.Blocks.

Mengapa saya tidak dapat langsung mengubah definisi yang ada?

Jika Anda ingin tahu mengapa Anda tidak dapat mengubah definisi yang ada, lanjutkan membaca. Kita akan mempertimbangkan beberapa kemungkinan.

Mengubah definisi yang ada secara langsung

Ada dua cara untuk mengubah definisi blok yang ada secara langsung: monkeypatching dan membuat fork kode. Keduanya sangat tidak dianjurkan, karena Anda akan berisiko merusak kode yang bergantung pada kode yang di-monkeypatch atau di-fork. Kedua teknik tersebut juga mempersulit integrasi update dan perbaikan bug. Untuk informasi selengkapnya, lihat Bagaimana dengan monkeypatching? dan Fork Blockly.

Membuat subclass definisi yang ada

Anda mungkin ingin membuat subclass definisi yang ada. Sayangnya, hal ini tidak mungkin karena definisi blok bukan class, melainkan mixin. Misalnya, tidak ada cara untuk menimpa properti warna karena definisi tidak memiliki properti warna. Sebagai gantinya, fungsi ini memiliki fungsi init yang memanggil setColour untuk menetapkan properti warna pada blok. Karena panggilan berada di dalam init, tidak ada cara untuk menggantinya tanpa mengganti seluruh fungsi init.

Menimpa fungsi dalam definisi yang ada

Anda dapat menimpa fungsi dalam definisi yang ada:

Blockly.Blocks['existing_block'].init = function() {/*new function*/};

Cara ini berfungsi, tetapi Anda harus menyalin dan mengubah fungsi yang ada -- Anda tidak dapat mengganti hanya satu baris secara ajaib. Ada beberapa masalah terkait hal ini:

  • Cara ini tidak jauh berbeda dengan menyalin dan mengubah seluruh definisi.
  • Anda tidak dapat menggunakannya untuk mengubah fungsi init blok yang ditentukan dalam JSON, seperti blok bawaan Blockly. Hal ini karena tidak ada fungsi init yang akan disalin -- fungsi ini dibuat saat runtime.
  • Anda harus menentukan blok menggunakan JavaScript, yang dapat menyebabkan masalah dengan lokalisasi.

Menimpa hasil init

Salah satu cara untuk "mengganti hanya satu baris" fungsi init adalah dengan mengganti fungsi init dengan fungsi yang memanggil fungsi init asli, lalu menulis ulang hasil panggilan tersebut. Misalnya, kode berikut mengubah warna blok logic_null:

const originalInit = Blockly.Blocks['logic_null'].init;
Blockly.Blocks['logic_null'].init = function() {
  originalInit.call(this);
  this.setColour(300);
}

Sayangnya, hal ini tidak terlalu berguna. Contoh:

  • Memperluas pemeriksaan koneksi atau menerapkan validator kolom yang kurang ketat dapat membatalkan asumsi yang dibuat oleh generator kode blok dan pengendali peristiwa.

  • Mengganti kolom dengan input nilai akan merusak generator kode blok dan validator kolom serta dapat merusak pengendali peristiwa. Hal ini mungkin juga sangat sulit dilakukan untuk blok yang dilokalkan karena lokalitas yang berbeda dapat menghasilkan blok dengan jenis dan urutan input dan kolom yang berbeda.

Menutupi pasangan nilai kunci dalam definisi JSON

Jika JSON untuk blok tersedia secara publik, Anda mungkin dapat menimpa setiap nilai JSON. Contoh:

// Block definition.
blockJson = {...};
Blockly.Blocks['my_block'] = {
  init: function() {
    initJson(blockJson); // Called when the block is created.
  }
}

// Third-party code.
blockJson.colour = 100;

Namun, ini hanya berfungsi jika objek JSON tersedia secara publik, definisi menentukan fungsi init secara eksplisit, dan fungsi init memanggil initJson. Ini tidak berfungsi jika JSON diteruskan ke defineBlocksWithJsonArray atau createBlockDefinitionsFromJsonArray karena JSON diproses sebelum pihak ketiga memiliki kesempatan untuk mengubahnya. (Perhatikan bahwa blok bawaan Blockly menggunakan createBlockDefinitionsFromJsonArray.)

Namun, bagaimana jika JSON tidak ditentukan dengan cara ini? Bukankah masih memungkinkan untuk menulis ulang properti JSON? Sayangnya, tidak. Definisi ini berisi fungsi init (bukan JSON) dan tidak ada fungsi untuk mengonversi fungsi init menjadi JSON.

// Doesn't work. There is no getJson() function.
const json = Blockly.Blocks['existing_block'].getJson();
json['message0'] = 'my new message0';
Blockly.Blocks['existing_block'].init = function () {
  initJson(json);
};

Mendesain untuk digunakan kembali

Saat mendesain blok kustom Anda sendiri, Anda mungkin dapat mendesainnya dengan cara yang mendorong penggunaan kembali.

Menggunakan kembali JSON

Jika memiliki dua blok yang secara substansial serupa, Anda dapat membuat definisi JSON induk dan menggunakannya kembali dalam definisi turunan. Contoh:

const parentJson = {
  // shared properties
};

Blockly.Blocks['child_block_1'] = {
  init: function() {
    initJson({...parentJson, colour: 100})
  }
}

Blockly.Blocks['child_block_2'] = {
  init: function() {
    initJson({...parentJson, colour: 200})
  }
}

Alternatif lainnya adalah menentukan JSON dalam objek yang tersedia secara publik dan meneruskan objek tersebut ke initJson dalam fungsi init Anda. Hal ini memungkinkan orang lain menimpa setiap properti. Untuk mengetahui informasi selengkapnya, lihat Menulis ulang pasangan nilai kunci dalam definisi JSON.

Menggunakan kembali fungsi

Blok dapat menentukan sejumlah fungsi standar, seperti pengendali peristiwa tingkat blok, tooltip kustom, validator kolom, dan fungsi yang digunakan oleh pengubah, serta fungsi yang memberikan perilaku kustom, seperti fungsi yang menetapkan nilai kolom dari data eksternal, seperti posisi lengan robot saat ini.

Anda mungkin dapat menggunakan kembali fungsi ini di seluruh blok.

Menggunakan kolom dropdown

Jika memiliki kumpulan blok yang pada dasarnya sama, kecuali untuk operator, Anda mungkin dapat mendesain satu blok yang memiliki kolom dropdown untuk operator. Contoh:

  • Blok logic_operation bawaan menggunakan dropdown dengan operator and dan or.
  • Blok math_arithmetic bawaan menggunakan dropdown dengan operator +, -, ×, ÷, dan ^.

Menulis generator kode untuk blok tersebut biasanya sedikit lebih kompleks, tetapi masih lebih mudah daripada menulis dan mengelola beberapa blok.

Menggunakan pengubah

Jika memiliki kumpulan blok yang mewakili variasi berbeda dari struktur pemrograman yang sama, Anda mungkin dapat membuat satu blok yang menggunakan mutator. Misalnya, blok controls_if bawaan dapat mewakili beberapa variasi pernyataan if-then-else.