Вітаємо! Ви щойно об’їхали глобус системи / мови програмування, приїхавши на інший бік світу, звідки ви вирушили. Ви щойно приземлилися на межі об'єктів на динамічній мові / прототипі!
Багато динамічних мов (наприклад, JavaScript, PHP, Python) дозволяють розширювати або змінювати властивості об'єкта під час виконання.
Крайньою формою цього є мова, заснована на прототипі, як Self або JavaScript. У них немає занять, строго кажучи. Ви можете робити речі, схожі на класове, об'єктно-орієнтоване програмування з успадкуванням, але правила сильно розслаблені порівняно з більш чітко визначеними мовами на основі класів, як Java та C #.
Язики на зразок PHP та Python живуть в середній частині. Вони мають регулярні, ідіоматичні системи на основі класів. Але атрибути об'єктів можна додавати, змінювати або видаляти під час виконання - хоча і з деякими обмеженнями (наприклад, "крім вбудованих типів"), яких ви не можете знайти в JavaScript.
Великий компроміс для цього динамізму - продуктивність. Забудьте про те, наскільки сильно або слабко набрано мову, або наскільки добре її можна скласти до машинного коду. Динамічні об'єкти повинні бути представлені у вигляді гнучких карт / словників, а не простих структур. Це додає накладних витрат на кожен доступ до об'єкта. Деякі програми намагаються зменшити накладні витрати (наприклад, з фантомним завданням kwarg та на базі ігрових класів на Python), але додаткові накладні витрати, як правило, дорівнюють курсу та ціні вступу.
Повертаючись до свого дизайну, ви прищеплюєте можливість мати динамічні властивості на підмножину класів. А Product
може мати змінні атрибути; імовірно, Invoice
це Order
буде чи не могла. Це не поганий шлях. Це дає вам можливість мати різні варіанти там, де вам це потрібно, залишаючись у суворій, дисциплінованій системі мови та типу. З нижньої сторони ви несете відповідальність за управління цими гнучкими властивостями, і вам, ймовірно, доведеться це робити через механізми, які виглядають дещо відмінними від більш рідних атрибутів. p.prop('tensile_strength')
а не p.tensile_strength
, наприклад, і p.set_prop('tensile_strength', 104.4)
, ніжp.tensile_strength = 104.4
. Але я працював і створив багато програм на мовах Pascal, Ada, C, Java і навіть динамічних мовах, які використовували саме такий доступ до встановлення для нестандартних типів атрибутів; підхід очевидно працездатний.
Між іншим, ця напруга між статичними типами та дуже різноманітним світом надзвичайно поширена. Аналогічна проблема часто виникає при розробці схеми баз даних, особливо для реляційних та передреляційних сховищ даних. Іноді це вирішується шляхом створення "надрядкових рядків", які містять достатню гнучкість, щоб містити або визначати об'єднання всіх уявлених варіацій, а потім заповнюючи будь-які дані, що потрапляють у ці поля. WordPress wp_posts
таблиця , наприклад, має поле , такі як comment_count
, ping_status
, post_parent
і post_date_gmt
що тільки цікаво при деяких обставинах, і що на практиці часто гаснути. Інший підхід - це дуже запасна, нормалізована таблиця, як wp_options
, наприклад, вашаProperty
клас. Хоча це вимагає більш чіткого керування, елементи в ньому рідко пусті. Об'єктно-орієнтовані та бази даних документів (наприклад, MongoDB) часто легше розбираються зі зміною параметрів, оскільки вони можуть створювати та встановлювати атрибути майже за власним бажанням.