Я в первую очередь программист на C ++, и я привык иметь такие шаблоны классов, как std::unique_ptr
, std::shared_ptr
и т. д. для выражения права собственности на мои объекты. Есть ли в Delphi что-нибудь похожее в стандартной библиотеке? Существуют ли передовые практики для выражения владения объектами, которым я должен следовать при написании своего кода?
Редактировать: Поскольку C ++ 11 стал стандартом, есть два легких вспомогательных класса, std::shared_ptr
а также std::unique_ptr
,
Если я создаю переменную типа std::shared_ptr<int>
, он представляет указатель на int с общим владением: под капотом подсчитывается ссылка, а когда ref-count достигает нуля, указатель автоматически освобождается. Этот тип выражает своего рода «совместное владение», когда многие объекты несут ответственность за уничтожение ресурса, когда они завершают работу с ним.
По сравнению, std::unique_ptr
выражает единоличное владение Когда unique_ptr выходит из области видимости, ресурс автоматически освобождается. std :: unique_ptr не может быть скопирован: одновременно может быть только один объект, владеющий этим ресурсом, и только один объект отвечает за очистку объекта.
Сравните эти легкие классы с голым указателем на int, где он может представлять либо общее владение, уникальное владение, либо он может быть просто ссылкой на объект где-то еще! Тип ничего не говорит вам.
Мой вопрос: поскольку Delphi поддерживает хранение ссылок на объекты, существуют ли какие-либо механизмы для явного указания: «Я являюсь единственным владельцем этого объекта, когда я закончу с ним, я освобожу его», против «я просто сохраняю ссылка на этот объект вокруг с целью взаимодействия с ним, но кто-то другой очистит его «против», я делюсь этим объектом со многими другими объектами, и тот, кто имеет его последним, получает возможность его очистить «.
Я знаю, что Collections.Generics имеет различные коллекции, такие как TList
против TObjectList
где TObjectList освободит членов, хранящихся в нем, а TList — нет. Вы можете сказать, что TObjectList «владеет» своими элементами, а TList — нет. Это суть моего вопроса, правда. Разрабатывая мои собственные классы, есть ли способы прямо выразить эти виды прав собственности на языке? Или есть ли лучшие практики / соглашения об именах, которые распространены среди разработчиков?
Я не знаю ни о каких языковых конструкциях, которые могут помочь, ни о каких-либо «стандартных соглашениях по именованию».
Однако давно я принял следующее соглашение об именах, чтобы упростить проверку правильности очистки классов за собой:
Очень грубо, но это работает, и очень помогло при просмотре кода, который вы давно не видели, чтобы предотвратить эти «Подождите, разве эта ссылка не должна быть освобождена или очищена?» поиск.
std :: unique_ptr нельзя скопировать: одновременно может быть только один объект, владеющий этим ресурсом
В языке Delphi нет ни типа, ни механизма, который бы препятствовал разделению «владения». Копия любой ссылки всегда может быть сделана. (Читайте: в Delphi нет ничего, что позволяло бы вам блокировать назначение, так как Дэвид красиво выразился.)
Когда unique_ptr выходит из области видимости, ресурс автоматически освобождается.
В Delphi это возможно только с (или через) интерфейсами. У Delphi нет сборщика мусора.
И есть только один объект, который отвечает за очистку объекта.
Ответственность за уборку вы должны обеспечить самостоятельно. Или делегируйте эту задачу (другой) фреймворк. Например, класс по умолчанию Delphi VCL TComponent
реализует автоматическое владение (и уничтожение), которое при желании можно обменять / контролировать RemoveComponent
а также InsertComponent
,
Разрабатывая мои собственные классы, есть ли способы прямо выразить эти виды прав собственности на языке? Или есть ли лучшие практики / соглашения об именах, которые распространены среди разработчиков?
Не совсем по теме, но, безусловно, по теме: существует несколько реализаций шаблона проектирования «singleton», которые обеспечивают одноразовое создание объектов.
Относительно соглашений об именах: термин «Владелец» (или «OwnsObjects» из вашего собственного примера) определенно выражает владение в том смысле, что этот владелец позаботится об уничтожении в случае необходимости. Таким образом, кнопка, созданная с формой в качестве владельца (единственный параметр конструктора кнопки по умолчанию), не требует ручного уничтожения.
Концепции в Delphi во многих случаях отличаются от C ++. Оба языка являются третьим поколением, но Delphi любит работать на более высоком уровне абстракции, чем C ++. Например, Delphi поддерживает указатели, но они редко используются, если придерживаться концепции ссылки, которая не совсем такая же, как в C ++.
В Delphi переменные объекта на самом деле являются ссылками (или на более низком уровне абстракции они являются указателями). В C ++, когда вы объявляете переменную объекта, конструктор вызывается немедленно, в Delphi это не так, и вам нужно вызвать его в данный момент, что выделит память и запустит конструктор. Итак, управление памятью объектов в C ++ и Delphi обусловлено разными жизненными циклами.
Все это было сказано просто для того, чтобы сказать вам, что стиль разработки управления памятью в Delphi отличается от C ++. Вот почему в Delphi нет вспомогательного класса, который бы делал именно то, что вы хотите. Тем не менее, Delphi предлагает концепцию Interfaces
, которые не существуют в C ++ (по крайней мере, не было, когда я работал с C ++, давным-давно). Интерфейсы похожи на абстрактный класс в том смысле, что у них нет кода. Вы должны предоставить реализацию интерфейса для интерфейса, и этот класс предоставит код. Тем не мение, Interfaces
обеспечить управление памятью подсчета ссылок, которое, я считаю, близко к тому, что вы ищете.
Итак, мой ответ вам: ближайшая языковая конструкция, которую Delphi может предложить вам в плане управления памятью, которая может быть использована для ваших целей: Интерфейсы. Итак, я предлагаю вам изучить его хотя бы немного, чтобы сделать свои собственные выводы.