Концепция, используемая в объектно-ориентированном программировании
В компьютерном программировании черта — это концепция, используемая в языках программирования и представляющая собой набор методов , которые можно использовать для расширения функциональности класса . [1] [2]
Обоснование
В объектно-ориентированном программировании поведение иногда разделяется между классами, которые не связаны друг с другом. Например, многие несвязанные классы могут иметь методы для сериализации объектов в JSON . Исторически сложилось так, что существовало несколько подходов к решению этой проблемы без дублирования кода в каждом классе, которому требовалось такое поведение. Другие подходы включают множественное наследование и миксины , но у них есть недостатки: поведение кода может неожиданно измениться, если изменить порядок применения миксинов или если к родительским классам или миксинам добавляются новые методы.
Черты решают эти проблемы, позволяя классам использовать эту черту и получать желаемое поведение. Если класс использует более одного признака, порядок использования этих признаков не имеет значения. Методы, предоставляемые типажами, имеют прямой доступ к данным класса.
Характеристики
Трейты объединяют аспекты протоколов (интерфейсов) и миксинов . Как и интерфейс, черта определяет одну или несколько сигнатур методов , реализации которых должны обеспечивать реализующие классы. Как и примесь, черта обеспечивает дополнительное поведение реализующего класса.
В случае конфликта имен между методами, предоставляемыми разными характеристиками, программист должен явно устранить неоднозначность, какой из этих методов будет использоваться в классе; тем самым вручную решая алмазную проблему множественного наследования . Это отличается от других методов композиции в объектно-ориентированном программировании, где конфликтующие имена автоматически разрешаются правилами области видимости .
Операции, которые можно выполнять с признаками, включают: [3] [4]
- симметричная сумма : операция, которая объединяет два непересекающихся признака для создания нового признака.
- переопределить (или асимметричную сумму ): операция, которая формирует новый признак путем добавления методов к существующему признаку, возможно, переопределяя некоторые из его методов.
- псевдоним : операция, которая создает новый признак путем добавления нового имени к существующему методу.
- исключение : операция, которая формирует новый признак путем удаления метода из существующего признака. (Объединение этого с операцией псевдонима дает неглубокую операцию переименования).
Если метод исключен из признака, этот метод должен быть предоставлен классом, который использует этот признак, или родительским классом этого класса. Это связано с тем, что методы, предоставляемые этим признаком, могут вызывать исключенный метод.
Состав признаков является коммутативным (т.е. для данных признаков A и B A + B эквивалентно B + A ) и ассоциативным (т. е . для данных признаков A , B и C ( A + B ) + C эквивалентно A + ( B + С )). [1]
Ограничения
Хотя черты предлагают значительные преимущества перед многими альтернативами, у них есть свои ограничения.
Требуемые методы
Если признак требует, чтобы класс-потребитель предоставил определенные методы, признак не может знать, являются ли эти методы семантически эквивалентными потребностям признака. Для некоторых динамических языков, таких как Perl, требуемый метод можно идентифицировать только по имени метода, а не по полной сигнатуре метода , что затрудняет гарантию соответствия требуемого метода.
Исключение методов
Если метод исключен из типажа, этот метод становится «обязательным» методом для этого типажа, поскольку его могут вызывать другие методы типажа.
Поддерживаемые языки
Признаки происходят из языка программирования Self [5] и поддерживаются следующими языками программирования:
- AmbientTalk : сочетает в себе свойства свойств Self (множественное наследование на основе объектов) и свойств Smalltalk Squeak (требующих явного составления признаков программистом). Он основан на исследованиях свойств с сохранением состояния и замораживаемых свойств, чтобы обеспечить состояние внутри признаков, что не допускалось в первых определениях. [6]
- C# : Начиная с версии 8.0, C# поддерживает методы интерфейса по умолчанию , [7] которые имеют некоторые свойства типажей. [8]
- C++ : используется в стандартной библиотеке шаблонов и стандартной библиотеке C++ для поддержки универсальных классов контейнеров [9] [10] , а также в библиотеке Boost TypeTraits. [11]
- Curl : Абстрактные классы как примеси допускают реализацию методов и, таким образом, представляют собой черты с другим именем. [ нужна цитата ]
- Крепость [12]
- Groovy : начиная с версии 2.3 [13]
- Haskell : В Haskell трейты называются классами типов .
- Haxe : Начиная с версии 2.4.0. [14] В руководстве называется статическим расширением [15]
using
, оно использует ключевое слово - Java : Начиная с версии 8, в Java есть поддержка методов по умолчанию , [16] которые имеют некоторые свойства типажей. [17] [18] [19] [20]
- JavaScript : Трейты могут быть реализованы с помощью функций и делегирования [21] или с помощью библиотек, предоставляющих трейты. [22] [23] [24]
- Джулия : Некоторые пакеты реализуют особенности, например, [25]
- Котлин : Трейты называются интерфейсами [26] начиная с M12. [27]
- Лассо [28]
- Моджо : начиная с версии 0.6.0 [29]
- OCaml : Трейты могут быть реализованы с использованием различных функций языка: включение модулей и типов модулей, функторы и типы функторов, наследование классов и типов классов и т. д.
- Perl : называются ролями , они реализованы в библиотеках Perl, таких как Moose , Role::Tiny и Role::Basic. Роли являются частью родственного языка Раку . [30] С принятием предложения Коринны ООП [31] Perl будет иметь родные для языка роли как часть современной ООП-системы.
- PHP : Начиная с версии 5.4, [32] [33] PHP позволяет пользователям указывать шаблоны, которые предоставляют возможность «наследовать» от более чем одного (признака) класса, в качестве псевдомножественного наследования .
- Python : через стороннюю библиотеку, [34] [35] или через классы миксинов более высокого порядка [36]
- Racket : поддерживает черты в виде библиотеки и использует макросы, структуры и первоклассные классы для их реализации. [37]
- Ruby : миксины модулей можно использовать для реализации трейтов. [38]
- Ржавчина [39]
- Черта Scala [40] [41] встроена и поддерживается ключевым словом
trait
. - Smalltalk : функции реализованы в двух диалектах Smalltalk: Squeak [1] и Pharo . [42]
- Swift : Трейты могут быть реализованы с помощью расширений протокола . [43]
Примеры
С#
В C# 8.0 можно определить реализацию как член интерфейса.
используя систему ; пространство имен CSharp8NewFeatures ; интерфейс ILogger { // Традиционные методы интерфейса void Log ( string message ); void LogError ( Исключение ) ; // Метод интерфейса по умолчанию void LogWarning ( строковое сообщение ) { Console . WriteLine ( сообщение ); } } class Logger : ILogger { public void Log ( строковое сообщение ) { Console . WriteLine ( сообщение ); } public void LogError ( Исключение ) { Console . WriteLine ( исключение . ToString ()); } } класс Program { static void Main ( string [] args ) { ILogger logger = новый Logger (); регистратор . LogWarning ( "Некоторое предупреждающее сообщение" ); } }
PHP
В этом примере используется черта для улучшения других классов:
// Черта шаблона TSingleton { Private static $_instance = null ; частная функция __construct () {} // Должен иметь частный конструктор по умолчанию, и помните, что его нельзя открывать в классе общественная статическая функция getInstance () { if ( null === self :: $_instance ) { self :: $_instance = new self (); } вернуть себя :: $_instance ; } }класс FrontController { используйте TSingleton ; }// Также может использоваться в уже расширенных классах class WebSite расширяет SomeClass { use TSingleton ; }
Это позволяет моделировать аспекты множественного наследования:
черта TBounding { public $x , $y , $width , $height ; }черта TMoveable { public function moveTo ( $x , $y ) { // … } }типаж TResizeable { public function resize ( $newWidth , $newHeight ) { // … } }класс Rectangle { use TBounding , TMoveable , TResizeable ; публичная функция fillColor ( $color ) { // … } }
Ржавчина
Трейт в Rust объявляет набор методов, которые должен реализовать тип. [44] Компиляторы Rust требуют эксплицирования трейтов, что обеспечивает безопасность дженериков в Rust.
// тип T должен иметь признак "Ord" , // чтобы можно было выполнять операции ">" и "<" fn max < T : Ord > ( a : & [ T ]) -> Option <& T > { let мут результат = а . первый () ? ; для n в a { if * n > * result { result = & n ; } } Некоторые ( результат ) }
Чтобы упростить утомительную и повторяющуюся реализацию таких свойств, как Debug
и Ord
, derive
макрос можно использовать для запроса компиляторов автоматически генерировать определенные реализации. [45] К производным признакам относятся: Clone
, Copy
, Debug
, Default
, , PartialEq
, Eq
, PartialOrd
и Ord
.Hash
Смотрите также
Рекомендации
- ^ abc Шерли, Натанаэль; Дюкасс, Стефан; Ньерстраз, Оскар ; Блэк, Эндрю П. (2003). «Черты характера: составные единицы поведения» (PDF) . Материалы Европейской конференции по объектно-ориентированному программированию (ECOOP) . Конспекты лекций по информатике. 2743 . Спрингер: 248–274. CiteSeerX 10.1.1.1011.8 . дои : 10.1007/978-3-540-45070-2_12. ISBN 978-3-540-45070-2.
- ^ Дюкасс, Стефан; Ньерстраз, Оскар; Шерли, Натанаэль; Вуйтс, Роэл; Блэк, Эндрю П. (март 2006 г.). «Черты: механизм мелкозернистого повторного использования». Транзакции ACM в языках и системах программирования . 28 (2): 331–388. CiteSeerX 10.1.1.64.2480 . дои : 10.1145/1119479.1119483. S2CID 16434119.
- ^ Фишер, Кэтлин ; Реппи, Джон (2003). «Статически типизированные признаки» (PDF) . Чикагский университет . Архивировано (PDF) из оригинала 17 мая 2004 г.
- ^ Фишер, Кэтлин; Реппи, Джон (2004). Типизированное исчисление признаков (PDF) . 11-й семинар по основам объектно-ориентированного программирования. Чикагский университет .
- ^ Карри, Гаэль; Баер, Ларри; Липки, Дэниел; Ли, Брюс (1982). Черты: подход к созданию подклассов с множественным наследованием . Конференция SIGOA по офисным информационным системам. Филадельфия, Пенсильвания, США: ACM Press. стр. 1–9. дои : 10.1145/966873.806468.
- ^ Ван Катсем, Том; Бергель, Александр; Дюкасс, Стефан; Де Мойтер, Вольфганг (2009). Добавление контроля состояния и видимости к признакам с использованием лексической вложенности (PDF) . Европейская конференция по объектно-ориентированному программированию (ECOOP 2009). Конспекты лекций по информатике. Том. 5653. Шпрингер-Верлаг. стр. 220–243. CiteSeerX 10.1.1.372.1265 . дои : 10.1007/978-3-642-03013-0_11. ISBN 978-3-642-03012-3.
- ^ «Методы интерфейса по умолчанию». Что нового в C# 8.0 . Майкрософт . Проверено 29 ноября 2019 г.
- ^ «Интерфейсы в C# 8.0 претерпевают изменения» . Реализация по умолчанию в интерфейсах C# 8.0 . Говоря о Дотнете. 9 сентября 2019 года . Проверено 29 ноября 2019 г.
- ^ "iterator_traits<Итератор>". Стандартная библиотека шаблонов . СГИ.
- ^ Майерс, Натан К. (июнь 1995 г.). «Черты: новая и полезная техника шаблонов». Отчет С++ . Проверено 23 января 2016 г.
- ^ Абрахамс, Дэвид. «Общие методы программирования: особенности». Библиотеки Boost C++ . Проверено 23 января 2016 г.
- ^ Стил, Гай; Мессен, Ян-Виллем (11 июня 2006 г.). «Учебник по языку программирования Fortress» (PDF) . Сан Микросистемс . Проверено 23 января 2016 г.
- ^ «Объектная ориентация: особенности». Язык программирования Groovy . Проверено 23 января 2016 г.
- ^ "Haxe 2.4.0 - Haxe - Кроссплатформенный набор инструментов" . Haxe — кроссплатформенный набор инструментов . Проверено 12 сентября 2017 г.
- ^ «Руководство - Haxe - Кроссплатформенный набор инструментов» . Haxe — Кроссплатформенный набор инструментов . Проверено 12 сентября 2017 г.
- ^ «Методы по умолчанию». Учебники по Java . Оракул . Проверено 23 января 2016 г.
- ^ Ликори, Луиджи; Спивак, Арно (2008). «FeatherTrait: скромное расширение полулегкой Java». Транзакции ACM в языках и системах программирования . 30 (2): 11:1. дои : 10.1145/1330017.1330022 . S2CID 17231803.
- ^ Ликори, Луиджи; Спивак, Арно (2008). «Расширение FeatherTrait Java с помощью интерфейсов». Теоретическая информатика . 398 (1–3): 243–260. дои : 10.1016/j.tcs.2008.01.051 . S2CID 12923128.
- ^ Боно, Вивиана; Менса, Энрико; Наддео, Марко (сентябрь 2014 г.). Специализированное программирование на Java 8. Международная конференция по принципам и практикам программирования на платформе Java: виртуальные машины, языки и инструменты (PPPJ '14). стр. 181–6. CiteSeerX 10.1.1.902.161 . дои : 10.1145/2647508.2647520.
- ↑ Форслунд, Эмиль (3 февраля 2016 г.). «Определение шаблона черт в Java». Эпоха Явы . Архивировано из оригинала 4 августа 2016 года . Проверено 3 февраля 2016 г.
- ↑ Селигер, Питер (11 апреля 2014 г.). «Множество талантов JavaScript» . Проверено 23 января 2015 г.
- ^ «Traits.js: особенности для JavaScript» . Проверено 23 января 2016 г.
- ^ Ван Катсем, Том; Миллер, Марк С. (2012). «Надежная композиция признаков для Javascript» (PDF) . Наука компьютерного программирования . Проверено 23 января 2016 г.
- ^ "КоктейльJS" . Проверено 23 января 2016 г.
- ^ мауро3. "SimpleTraits.jl". Гитхаб . Проверено 23 марта 2017 г.
{{cite web}}
: CS1 maint: numeric names: authors list (link) - ^ «Интерфейсы». Справочник по Котлину . ДжетБрэйнс . Проверено 23 января 2016 г.
- ^ Бреслав, Андрей (29 мая 2015 г.). «Котлин М12 вышел!». Котлин-блог . ДжетБрэйнс . Проверено 23 января 2016 г.
- ^ «Черты». Руководство по языку Лассо . ЛассоСофт. 6 января 2014 года . Проверено 23 января 2016 г.
- ^ «Модульная документация — журнал изменений Mojo🔥» . docs.modular.com . Проверено 13 декабря 2023 г.
- ^ хроматический (30 апреля 2009 г.). «Почему роли Perl» . Проверено 23 января 2016 г.
- ^ Кертис «Овидий» По. «Предложение Коринны ООП». Коринна RFC . Проверено 30 сентября 2022 г.
- ^ «Черты». PHP-документация . Группа PHP . Проверено 23 января 2016 г.
- ↑ Марр, Стефан (9 января 2011 г.). «Запрос комментариев: горизонтальное повторное использование PHP». PHP.net вики . Группа PHP . Проверено 31 января 2011 г.
- ^ Перя, Теппо. «Документация py3traits» . Проверено 23 января 2016 г.
- ^ Перя, Теппо (25 марта 2015 г.). "py2traits". Гитхаб . Проверено 23 января 2016 г.
- ^ «Классы миксинов высшего порядка». Архивировано из оригинала 9 октября 2016 г.
- ^ «Черты». Справочник по рэкету . Проверено 23 января 2016 г.
- ↑ Дэвид Нэсби (14 февраля 2004 г.). «Черты Рубина». Руби Нэсби . Проверено 23 января 2016 г.
- ^ «Черты». Язык программирования Rust . Проверено 30 сентября 2019 г.
- ^ «Черты». Экскурсия по Скале . Федеральная политехническая школа Лозанны . Проверено 23 января 2016 г.
- ↑ Ньюард, Тед (29 апреля 2008 г.). «Руководство для занятого Java-разработчика по Scala: особенности и поведение». IBM DeveloperWorks . ИБМ . Проверено 23 января 2016 г.
- ^ «Черты характера за 10 минут». Фаро: Книга CollaborActive . Проверено 23 января 2016 г.
- ↑ Холлеманс, Маттейс (22 июля 2015 г.). «Миксины и трейты в Swift 2.0» . Проверено 23 января 2016 г.
- ^ «Особенности - Введение в программирование с использованием Rust» .
- ^ «Черты — язык программирования Rust» .
Внешние ссылки
- «Черты: составные единицы поведения». Группа создания программного обеспечения . Университет Берна.