Поздравляем! Вы только что совершили кругосветное плавание на языке программирования / системе типов, прибыв на другой край света, откуда вы отправились. Вы только что приземлились на границе динамического языка / прототипа объекта земли!
Многие динамические языки (например, 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) часто легче справляются с изменением параметров, поскольку они могут создавать и задавать атрибуты практически по желанию.