Возможно, несколько примеров помогут.
при создании класса и Вы хотите, чтобы он действовал как словарь, можно определить все различное __ __
необходимые методы. Но это - что-то вроде боли. Как альтернатива, можно просто определить некоторых и наследоваться (в дополнение к любому другому наследованию) от UserDict.DictMixin
(перемещенный в collections.DictMixin
в py3k). Это будет иметь эффект автоматического определения всей остальной части API словаря.
А второй пример: инструментарий GUI wxPython позволяет Вам делать средства управления списком с несколькими столбцами (как, скажем, дисплей файла в Windows Explorer). По умолчанию эти списки являются довольно основными. Можно добавить дополнительную функциональность, такую как способность отсортировать список по конкретному столбцу путем нажатия на заголовок столбца, путем наследования ListCtrl и добавления соответствующего mixins.
В Perl вы можете использовать DateTime , который позволяет такие вещи, как:
my $dt = DateTime->now
$dt->subtract( hours => 1 );
PowerShell имеет базовую поддержку. Например, 5 ГБ / 1 МБ
соответствует 5120
Синтаксически я не совсем уверен каковы преимущества
DateTime.Now + 60 years
Over
DateTime.Now.AddYears (60)
Мой типичный метод работы с «единицами» - это определение констант, которые преобразуют эти единицы в базовую единицу объекта данных при умножении. Поскольку кто-то (кратко) пометил это с помощью Ada, версия Ada будет выглядеть следующим образом:
Years : constant := 60.0 * 60.0 * 24.0 * 365.0;
DateTime.Now := DateTime.Now + (60.0 * Years);
Я думаю, что вы можете делать почти то же самое в C ++, за исключением того, что их временные объекты могут быть большими целыми числами вместо действительных.
Не является частью языка, но я видел это раньше в C, примерно так:
#define NOW time(0)
#define PLUS +
#define AND +
#define MINUS -
#define SECOND * 1
#define SECONDS * 1
#define MINUTE * 60
#define MINUTES * 60
#define HOUR * 3600
#define HOURS * 3600
#define DAY * 86400
#define DAYS * 86400
time_t waitUntil = NOW PLUS 1 HOUR AND 23 MINUTES;
В то время это казалось мне мерзостью, в том же классе, что и "# define begin {"
и "# define end}"
- если вам не нравится способ работы языка, используйте другой язык; не пытайся подчинить его своей воле таким ужасным образом.
Это все еще кажется мерзостью, но я смягчился в старости и, по крайней мере, могу понять, почему, возможно, кто-то подумал, что это хорошая идея.
Я уверен, что это не то, что вы ищете, но в области испытательного и измерительного оборудования для «тестовой программы» нет ничего необычного в том, чтобы включать утверждения, которые работают с значения, выраженные в единицах измерения напряжения, тока или времени.
Тем не менее, это очень специализированный материал, который не распознается большинством как языки программирования.
Функция PHP strtotime () делает это очень хорошо. Он принимает строку и необязательное время в качестве параметров и анализирует строку для определения нового времени.
Примеры:
$newTime = strtotime('last monday');
$newTime = strtotime('- 2 days', $originalTime);
$newTime = strtotime('- 60 years', $originalTime);
$newTime = strtotime('+ 1 week 1 day', $originalTime);
Подробнее здесь: http://us2.php.net/strtotime
Я не встречал такого языка, который бы поддерживал его по сути. Однако вы, конечно, можете написать свои собственные объекты на основе даты на различных языках, если хотите.
Frink - это язык, специально созданный для подобных «физических вычислений». Из документации:
Frink - практичный инструмент для расчетов. и язык программирования, предназначенный для сделать физические расчеты простыми, чтобы помочь обеспечить получение ответов право [..]. Он отслеживает единицы измерения (футы, метры, килограммы, ватты и т. д.) через все расчеты, что позволяет прозрачно смешивать единицы измерения [..]
Ваш пример во Фринке:
now[] - 60 years
Я знаю, что вы имеете в виду, и мне тоже это было любопытно. (Мой учитель химии в старшей школе был непреклонен в том, что числа без единиц не имеют смысла. В любом случае ...)
На любом строго типизированном языке вы можете писать классы для этих понятий. Я написал их на C ++, Java и Pascal. Погуглите «Единицы» и «Java», и вы найдете библиотеку, в которой есть все виды физических измерений, инкапсулированных таким образом.
C ++ с его удобными преобразованиями типов и перегрузкой операторов может сделать это более естественным. Вы действительно можете делать вещи довольно гладкими, добиваясь того, чего, я думаю, вы хотите. Java, хотя и делает это, потребует более явных преобразований и неудобного синтаксиса.
Но нет, я этого не видел.
Ищите предметно-ориентированные языки, созданные для ученых, даже "
SQL или, по крайней мере, MySQL имеет некоторую базовую поддержку единиц измерения времени.
mysql> SELECT DATE_SUB(NOW(), INTERVAL 1 DAY) AS `yesterday`, NOW() + INTERVAL 1 DAY AS `tomorrow`;
+---------------------+---------------------+
| yesterday | tomorrow |
+---------------------+---------------------+
| 2009-08-20 06:55:05 | 2009-08-22 06:55:05 |
+---------------------+---------------------+
1 row in set (0.00 sec)
MySQL имеет эту функцию
mysql> SELECT '2008-12-31 23:59:59' + INTERVAL 1 SECOND;
-> '2009-01-01 00:00:00'
mysql> SELECT INTERVAL 1 DAY + '2008-12-31';
-> '2009-01-01'
mysql> SELECT '2005-01-01' - INTERVAL 1 SECOND;
-> '2004-12-31 23:59:59'
Я не знаю, существует ли он еще, но я ожидал, что в ближайшие пару лет начнут появляться такие вещи, как DSL . Я думаю что-то вроде следующего поколения MATLAB или что-то в этом роде. Я уверен, что у таких вещей есть множество математических, научных и инженерных применений.
Когда вы используете единицы, вы фактически назначаете тип. Преобразования могут быть реализованы посредством литья или дифференцирования вызовов функций на основе типов параметров (перегрузка функций). Практически любой статически типизированный язык (который позволяет вам тщательно определять типы) позволит вам делать нечто подобное. Это сделало бы вашу программу более надежной, хотя те, кто предпочитает языки с динамической типизацией, могут возразить, что выигрыш невелик по сравнению со временем, потраченным на реализацию такой тщательной системы типов для большинства приложений. С другой стороны, создание Mars Climate Orbiter заслуживает такой системы.
Синтаксис немного отличается, но ваш пример кажется мне очень похожим на общие примеры того, как некоторые будут использовать систему типов Haskell (или любой типизированный функциональный язык), хотя, как я уже упоминал, это также возможно в C-подобные языки тоже.
Библиотека Java JODA работает именно так.
И есть JSR-275 , который предлагает структуру модулей.
Я впервые услышал о этот выпуск еще в 1997 году от Мартина Фаулера. Об этом он писал в «Паттерны анализа» .
Не единицы как таковые ... но один из способов использования методов расширения, чтобы дать вам функциональность, подобную единицам. Этот пример специально для TimeSpan.
static class TimeExtensions
{
public static TimeSpan ToDays(this int i)
{
return new TimeSpan(i, 0, 0, 0, 0);
}
public static TimeSpan ToHours(this int i)
{
return new TimeSpan(0, i, 0, 0, 0);
}
public static TimeSpan ToMinutes(this int i)
{
return new TimeSpan(0, 0, i, 0, 0);
}
public static TimeSpan ToSeconds(this int i)
{
return new TimeSpan(0, 0, 0, i, 0);
}
public static TimeSpan ToMilliseconds(this int i)
{
return new TimeSpan(0, 0, 0, 0, i);
}
}
Тогда просто 4.ToMinutes () даст вам TimeSpan равным 4 минутам. Если у вас есть аналогичные базовые классы, с которыми можно работать для представления других типов модулей,
См. Ответ на Расширения C # , где класс int расширен для поддержки такие методы, как Hours (), Days () и т. д.
Powershell имеет операторы kB, MB и GB для обработки размеров файлов и т. д.
Функция DATE_ADD () в MSSQL для арифметики даты принимаются такие единицы, как день, час и т. Д.
Новый язык Sun Fortress поддерживает единицы и, если память не изменяет, достаточно умен, чтобы мешать вам делать странные вещи, такие как вычитание времени из мер длины.
А в Mathematica есть единицы измерения и не слишком громоздкий синтаксис для их обработки.
Ada и его двоюродный брат, VHDL, напрямую поддерживают концепцию единиц. Поскольку эти языки чрезвычайно строго типизированы, единицы являются естественной способностью строгости типов.
Существует библиотека Boost C ++ для модулей, которая широко использует метапрограммирование шаблонов для обеспечения чего-то похожего на желаемый синтаксис.
quantity<force> F(2.0*newton);
quantity<length> dx(2.0*meter);
quantity<energy> E(work(F,dx));
http://www.boost.org/doc/ libs / 1_37_0 / doc / html / boost_units.html
Что ж, библиотека ActiveSupport для ruby расширяет класс Integer такими методами, как часы и дни, что позволяет писать такие вещи, как:
Time.now + 5.days
Но это не совсем синтаксическая функция - это просто вызов метода и это возможно на любом языке, который позволяет добавлять методы в существующий класс. Вы можете сделать это на C # с помощью методов расширения - хотя это должно быть там 5.days ()
.
Возможно, вас заинтересует поддержка F # Units of Measure
Unum делает почти то же самое, что и для Python, допуская такой код:
>>> TON + 500*KG
1.5 [t]
>>> 5E-8*M - 28*ANGSTROM
472.0 [angstrom]
>>> 3*H + 20*MIN + 15*S
3.3375 [h]
>>> H == 60*MIN
True
>>> 10000*S > 3*H + 15*MIN
False
>>>
С точки зрения дизайна, использование временных файлов будет более чистым, если эти данные не являются частью состояния объекта, и им следует отдавать предпочтение.
Никогда не выбирайте дизайн по соображениям производительности до фактического профилирования приложения. Вы можете просто обнаружить, что в итоге получите худший дизайн, который на самом деле не лучше, чем исходный дизайн с точки зрения производительности.
На все ответы, которые рекомендуют повторно использовать объекты, если стоимость строительства / разрушения высока, важно отметить что если вы должны повторно использовать объект от одного вызова к другому, во многих случаях объект должен быть сброшен в допустимое состояние между вызовами метода, и это также имеет свою стоимость. Во многих таких случаях стоимость сброса может быть сопоставима со строительством / разрушением.
Если вы не сбрасываете состояние объекта между вызовами, два решения могут дать разные результаты, так как в первом вызове аргумент будет инициализирован и состояние, вероятно, будет отличаться между вызовами методов.
Безопасность потоков также оказывает большое влияние на это решение. Автоматические переменные внутри функции создаются в стеке каждого из потоков и, как таковые, по своей сути являются потокобезопасными. Любая оптимизация, которая подталкивает эту локальную переменную, чтобы ее можно было повторно использовать между различными вызовами, усложнит безопасность потоков и может даже привести к снижению производительности из-за конкуренции, которая может ухудшить общую производительность.
Наконец, если вы хотите сохранить объект между вызовами методов я бы все равно не сделал его частным членом класса (он не является частью класса), а скорее деталью реализации (статическая переменная функции, глобальная в безымянном пространстве имен в модуле компиляции, где реализована doOperation, член PIMPL ... [первые 2 разделяют данные для всех объектов,