stringtranslate.com

это (компьютерное программирование)

this , self и Meключевые слова, используемые в некоторых языках программирования для обозначения объекта, класса или другого объекта, частью которого является текущий выполняющийся код. Таким образом, упомянутая сущность зависит от контекста выполнения (например, от того, у какого объекта вызывается метод). В разных языках программирования эти ключевые слова используются несколько по-разному. В языках, где ключевое слово типа «this» является обязательным, это ключевое слово — единственный способ получить доступ к данным и методам, хранящимся в текущем объекте. Если это необязательно, эти ключевые слова могут устранить неоднозначность переменных и функций с одинаковыми именами.

Объектно-ориентированного программирования

Во многих объектно-ориентированных языках программирования ( thisтакже называемая selfили Me) — это переменная, которая используется в методах экземпляра для ссылки на объект, над которым они работают. Первый объектно-ориентированный язык, SIMULA 67 , использовался thisдля явной ссылки на локальный объект. [1] : 4.3.2.3  C++ и языки, которые по стилю являются его производными (такие как Java , C# , D и PHP ), также обычно используют this. Smalltalk и другие, такие как Object Pascal , Perl , Python , Ruby , Rust , Objective-C , DataFlex и Swift , используют self. Microsoft Visual Basic использует Me.

Эта концепция одинакова во всех языках: thisобычно это неизменяемая ссылка или указатель , ссылающийся на текущий объект; текущий объект часто является кодом, который действует как «родительский» или «вызывающий» для свойства , метода , подпрограммы или функции, содержащей thisключевое слово. После того, как объект правильно сконструирован или создан, thisон всегда является допустимой ссылкой. Некоторые языки требуют этого явно; другие используют лексическую область видимости , чтобы неявно использовать ее для отображения символов внутри своего класса. Или, альтернативно, текущий объект, на который ссылается, thisможет быть независимым объектом кода, который вызвал функцию или метод, содержащий ключевое слово this. Такое случается, например, когда обработчик событий JavaScript , прикрепленный к тегу HTML на веб-странице, вызывает функцию, содержащую ключевое слово, thisхранящееся в глобальном пространстве вне объекта документа; в этом контексте thisбудет относиться к элементу страницы внутри объекта документа, а не к включающему его объекту окна. [2]

В некоторых языках, например C++, Java и Raku, thisили selfявляется ключевым словом , и переменная автоматически существует в методах экземпляра. В других, например Python, Rust и Perl 5, такой ссылкой является первый параметр метода экземпляра. Это необходимо указать явно. В Python и Perl параметр не обязательно должен иметь имя thisили self; Программист может свободно называть его, как и любой другой параметр. Однако по неофициальному соглашению первый параметр метода экземпляра в Perl или Python называется self. Rust требует, чтобы вызывался объект self &selfили self, в зависимости от того, заимствует ли вызываемая функция вызывающий объект или перемещает его соответственно.

Статические методы в C++ или Java связаны не с экземплярами, а с классами, и поэтому не могут использовать this, поскольку объекта нет. В других языках, таких как Ruby, Smalltalk, Objective-C или Swift, метод связан с объектом класса , который передается как this, и они называются методами класса . Для методов класса Python использует clsдля доступа к объекту класса .

Тонкости и сложности

Когда для вывода используется лексическая область видимости this, использование thisin в коде, хотя и не является незаконным, может вызвать тревогу у программиста сопровождения, хотя в этом случае все еще существуют законные варианты использования this, например, ссылка на переменные экземпляра, скрытые локальными переменными с тем же именем, или если метод хочет вернуть ссылку на текущий объект, то есть thisна самого себя.

В некоторых компиляторах (например , GCC ) указатели на методы экземпляра C++ могут быть напрямую приведены к указателю другого типа с явным thisпараметром указателя. [3]

Открытая рекурсия

Семантика диспетчеризации this, а именно динамическая диспетчеризация вызовов методов this, известна как открытая рекурсия и означает, что эти методы могут быть переопределены производными классами или объектами. Напротив, прямая именованная рекурсия или анонимная рекурсия функции использует закрытую рекурсию с ранним связыванием. Например, в следующем коде Perl для факториала токен __SUB__является ссылкой на текущую функцию:

используйте функцию «:5.16» ; суб { мой $ х = сдвиг ; == 0 ? 1 : $x * __SUB__ -> ( $x - 1 ); }                    

Напротив, в C++ ( thisдля ясности используется явное выражение, хотя и не обязательно) thisпривязка к самому объекту, но если метод класса был объявлен «виртуальным», т.е. полиморфным в базе, он разрешается посредством динамической отправки ( позднее связывание ), так что производные классы могут его переопределить.

unsigned int факториал ( unsigned int n ) { if ( n == 0 ) return 1 ; иначе верните n * this -> факториал ( n - 1 ); }                 

Этот пример является искусственным, поскольку это прямая рекурсия, поэтому переопределение factorialметода приведет к переопределению этой функции; более естественными примерами являются случаи, когда метод производного класса вызывает тот же метод базового класса или в случаях взаимной рекурсии. [4] [5]

В проблеме хрупкого базового класса обвиняют открытую рекурсию, при этом предполагается, что вызов методов по thisумолчанию использует закрытую рекурсию (статическая диспетчеризация, раннее связывание), а не открытую рекурсию (динамическая диспетчеризация, позднее связывание), используя открытую рекурсию только тогда, когда это специально просил; внешние вызовы (без использования this) будут динамически отправляться, как обычно. [6] [7] На практике в JDK эта проблема решается с помощью определенной дисциплины программиста; эта дисциплина была формализована К. Руби и Г. Т. Ливенсом; он состоит из следующих правил: [8]

Реализации

С++

Ранние версии C++ позволяли thisизменять указатель; таким образом программист мог изменить объект, над которым работал метод. Эта функция со временем была удалена, и теперь thisв C++ используется r-значение . [9]

Ранние версии C++ не включали ссылки, и было высказано предположение, что если бы они были такими в C++ с самого начала, thisони были бы ссылкой, а не указателем. [10]

C++ позволяет объектам уничтожать себя с помощью оператора исходного кода: delete this.

С#

Ключевое слово thisв C# работает для ссылочных типов так же, как и в Java. Однако в типах значений C# оно thisимеет совершенно другую семантику, оно похоже на обычную ссылку на изменяемую переменную и может даже встречаться в левой части присваивания.

Одним из вариантов использования thisв C# является разрешение ссылки на переменную внешнего поля внутри метода, который содержит локальную переменную с тем же именем. В такой ситуации, например, оператор внутри метода присваивает var n = localAndFieldname;тип и значение локальной переменной , тогда как оператор присваивает тип и значение переменной внешнего поля . [11]localAndFieldnamenvar n = this.localAndFieldname;n

Д

В D this метод класса, структуры или объединения относится к неизменяемой ссылке на экземпляр включающего агрегата. Классы являются ссылочными типами, а структуры и объединения — типами значений. В первой версии D ключевое слово thisиспользуется как указатель на экземпляр объекта, к которому привязан метод, тогда как в D2 оно имеет характер неявного refаргумента функции.

Дилан

В языке программирования Dylan , который является объектно-ориентированным языком, поддерживающим мультиметоды и не имеющим понятия this, отправка сообщения объекту по-прежнему сохраняется в синтаксисе. Две формы ниже работают одинаково; различия — всего лишь синтаксический сахар .

объект.метод(параметр1, параметр2)

и

метод (объект, параметр1, параметр2)

Эйфелева

В тексте класса текущий тип — это тип, полученный из текущего класса . Внутри функций (подпрограмм, команд и запросов) класса можно использовать ключевое слово Currentдля ссылки на текущий класс и его функции. Использование ключевого слова Currentне является обязательным, поскольку оно Currentподразумевается при простой открытой ссылке на имя текущего объекта класса. Например: в классе MY_CLASS может быть функция `foo', и обращаться к ней можно следующим образом:

 сорт МОИ ЗАНЯТИЯ  функция -- Доступ   фу : ЦЕЛОЕ ЧИСЛО   моя_функция : ЦЕЛОЕ ЧИСЛО  делать Результат := фу   конец  конец

[12]

Строка № 10 (выше) содержит подразумеваемую ссылку на Currentвызов простой `foo'.

Строка № 10 (ниже) содержит явную ссылку на Currentвызов Current.foo.

 сорт МОИ ЗАНЯТИЯ  функция -- Доступ   фу : ЦЕЛОЕ ЧИСЛО   моя_функция : ЦЕЛОЕ ЧИСЛО  делать Результат := Текущий . фу   конец  конец

Любой подход приемлем для компилятора, но подразумеваемая версия (например, x := foo) предпочтительнее, поскольку она менее многословна.

Как и в других языках, бывают случаи, когда использование ключевого слова Currentявляется обязательным, например:

 сорт МОИ ЗАНЯТИЯ  функция -- Доступ   моя_команда -- Создать MY_OTHER_CLASS с `Текущим' местный х : MY_OTHER_CLASS  делать создать х . make_with_something ( текущий )   конец  конец

В случае приведенного выше кода вызов make_with_something в строке №11 передает текущий класс путем явной передачи ключевого слова Current.

Джава

Ключевое слово this— это ключевое слово языка Java , которое представляет текущий экземпляр класса, в котором оно встречается. Он используется для доступа к переменным и методам класса.

Поскольку все методы экземпляра в Java виртуальны, thisони никогда не могут иметь значение null. [13]

JavaScript

В JavaScript, который представляет собой язык программирования или сценариев, широко используемый в веб-браузерах, thisявляется важным ключевым словом, хотя то, что оно оценивает, зависит от того, где оно используется.

Чтобы обойти различное значение thisвложенных функций, таких как обработчики событий DOM, в JavaScript распространенной идиомой является сохранение thisссылки на вызывающий объект в переменной (обычно называемой thatили self), а затем использование этой переменной для ссылки на вызывающий объект. объект во вложенных функциях.

Например:

// В этом примере $ является ссылкой на библиотеку jQuery $ ( ".element" ). hover ( function () { // Здесь и то, и это указывают на элемент под курсором мыши. var that = this ; $ ( this ). find ( '.elements' ).each ( function ( ) { // Здесь , это указывает на итерируемый элемент DOM. // Однако это все равно указывает на элемент под курсором мыши. $ ( this ). addClass ( "highlight" } ) ;             

Примечательно, что в JavaScript используются оба thisключевых слова, а также связанное с ними ключевое слово self[17] (в отличие от большинства других языков, которые, как правило, используют одно или другое), причем selfоно предназначено исключительно для веб-работников. [18]

Наконец, в качестве надежного способа конкретной ссылки на глобальный объект (окно или его эквивалент) в JavaScript используется globalThisключевое слово. [19]

Луа

В Lua selfсоздается как синтаксический сахар , когда функции определяются с помощью :оператора. [20] При вызове метода с использованием :индексируемый объект будет неявно указан в качестве первого аргумента вызываемой функции.

Например, следующие две функции эквивалентны:

локальный  объект  =  {}функция  объект . foo ( arg1 ,  arg2 )  print ( arg1 ,  arg2 )  — здесь нельзя использовать «self» endfunction  obj : bar ( arg )  print ( self ,  arg )  — «self» — это неявный первый аргумент перед концом arg-- Все функции можно вызывать обоими способами, с помощью "." или с ":"obj : foo ( "Foo" )  — эквивалент obj.foo(obj, "Foo") obj . bar ( obj ,  "Bar" )  — эквивалент obj:bar("Bar")

Lua сам по себе не является объектно-ориентированным, но в сочетании с другой функцией, называемой метатаблицами, использование selfпозволяет программистам определять функции способом, напоминающим объектно-ориентированное программирование.

PowerShell

В PowerShell специальная автоматическая переменная $_ содержит текущий объект в объекте конвейера. Эту переменную можно использовать в командах, которые выполняют действие над каждым объектом или над выбранными объектами в конвейере. [21]

«один» ,  «два» ,  «три»  |  %  {  напишите $_  }

Также, начиная с PowerShell 5.0, в котором добавлен формальный синтаксис для определения классов и других пользовательских типов, [22] $this переменная описывает текущий экземпляр объекта.

Питон

В Python нет ключевого слова для this. Когда функция-член вызывается для объекта, она вызывает функцию-член с тем же именем в объекте класса объекта, при этом объект автоматически привязывается к первому аргументу функции. Таким образом, обязательным первым параметром методов экземпляра является this; этот параметр традиционно называется self, но может быть назван как угодно.

В методах класса (созданных с помощью classmethodдекоратора) первый аргумент относится к самому объекту класса и обычно называется cls; они в основном используются для наследуемых конструкторов, [23] где использование класса в качестве параметра позволяет создать подкласс конструктора. В статических методах (созданных с помощью staticmethodдекоратора) специального первого аргумента не существует.

Ржавчина

В Rust типы объявляются отдельно от связанных с ними функций. Функции, аналогичные методам экземпляров в более традиционных объектно-ориентированных языках, должны явно принимать selfв качестве первого параметра. Эти функции затем можно вызывать с использованием instance.method()синтаксического сахара. Например:

struct  Foo { бар : i32 , }  impl Foo { fn new () -> Foo { Foo { bar : 0 , } } fn Refer ( & self ) { println! ( " {}" , self.bar ) ; } fn mutate ( & mut self , baz : i32 ) { self . бар = баз ; } fn потреблять ( self ) { self . ссылаться (); } }                               

Здесь определяется тип , Fooс четырьмя связанными функциями. Первая, Foo::new(), не является функцией экземпляра и должна быть указана с префиксом типа. Остальные три принимают selfпараметры различными способами и могут быть вызваны в Fooэкземпляре с использованием синтаксического сахара точечной нотации, что эквивалентно вызову имени функции с указанием типа с явным selfпервым параметром.

пусть mut foo = Foo :: new (); // должна вызываться как функция foo с указанным типом . ссылаться (); // печатает «0». Foo::refer() имеет доступ только для чтения к экземпляру foo foo . мутировать ( 5 ); // изменяет foo на месте, что разрешено спецификацией &mut, необходимо, чтобы foo был объявлен mut foo . потреблять (); // печатает "5" и уничтожает foo, поскольку Foo::consume() полностью владеет собой        // эквивалент foo.refer() Foo :: Refer ( foo ); // ошибка компиляции: foo выходит за пределы области видимости 

Себя

Язык Self назван в честь этого использования слова «self».

Xbase++

Selfиспользуется строго внутри методов класса. Другой способ ссылки Self— использовать ::.

Смотрите также

Рекомендации

  1. ^ Даль, Оле-Йохан ; Мирхауг, Бьёрн; Найгаард, Кристен (1970). «Общий базовый язык, Норвежский вычислительный центр».
  2. ^ Пауэлл, Томас А., и Шнайдер, Фриц, 2012. JavaScript: Полный справочник, третье издание. МакГроу-Хилл. Глава 11, Обработка событий , стр. 428. ISBN 978-0-07-174120-0 . 
  3. ^ Использование коллекции компиляторов GNU (GCC) — привязанные функции-члены.
  4. ^ «Закрытая и открытая рекурсия», Ральф Хинце, июль 2007 г.
  5. ^ Открытая рекурсия, Lambda the Ultimate
  6. ^ «Выборочная открытая рекурсия: решение проблемы хрупкого базового класса», Джонатан Олдрич
  7. ^ «Выборочная открытая рекурсия: решение проблемы хрупкого базового класса», Lambda the Ultimate
  8. ^ Олдрич, Джонатан и Кевин Доннелли. «Выборочная открытая рекурсия: модульные рассуждения о компонентах и ​​наследовании». SAVCBS 2004 Спецификация и проверка компонентных систем (2004): 26. со ссылкой на решение, принятое в JDK, C. Ruby и GT Leavens. «Безопасное создание правильных подклассов, не видя кода суперкласса». В «Системах объектно-ориентированного программирования, языках и приложениях», октябрь 2000 г. doi : 10.1145/353171.353186, также доступен как технический отчет TR № 00-05d.
  9. ^ ISO/IEC 14882:2003(E): Языки программирования — C++ . ИСО/МЭК. 2003.
  10. ^ Страуструп: Часто задаваемые вопросы по стилю и технике C++
  11. ^ Де Смет, Барт, 2011. C# 4.0 выпущен на свободу. Издательство Sams Publishing, Индианаполис, США. Глава 4, Основы языка , стр. 210. ISBN 978-0-672-33079-7 . 
  12. ^ ПРИМЕЧАНИЕ. Номера строк предназначены только для справочных целей. Eiffel не имеет номеров строк в тексте класса. Однако в Eiffel Studio IDE есть опция номера строки, которую можно дополнительно включить для справочных целей (например, парное программирование и т. д.).
  13. ^ Барнс, Д. и Кёллинг, М. Сначала объекты с Java . «...причина использования этой конструкции [this] заключается в том, что мы имеем ситуацию, известную как перегрузка имени : одно и то же имя используется для двух разных объектов... Важно понимать, что поля и параметры отдельные переменные, которые существуют независимо друг от друга, даже если они имеют одинаковые имена. Параметр и поле, имеющие одинаковое имя, не являются проблемой в Java». [ нужна цитата ]
  14. ^ Крокфорд, Дуглас, 2008. JavaScript: хорошие стороны . O'Reilly Media Inc. и Yahoo! Inc. Глава 4, Функции , стр. 28. ISBN 978-0-596-51774-8 
  15. ^ Пауэлл, Томас А., и Шнайдер, Фриц, 2012. JavaScript: Полный справочник, третье издание. МакГроу-Хилл. Глава 5, Функции , стр. 170–1. ISBN 978-0-07-174120-0 
  16. ^ Гудман, Дэнни, с Моррисоном, Майклом, 2004. Библия JavaScript, 5-е издание. Wiley Publishing, Inc., Индианаполис, США. Глава 33, Функции и пользовательские объекты , стр. 987. ISBN 0-7645-5743-2 
  17. ^ Сеть разработчиков Mozilla: Window.self
  18. ^ Сеть разработчиков Mozilla: API веб-работников
  19. ^ Сеть разработчиков Mozilla: globalThis
  20. ^ «Программирование на Lua: 16».
  21. ^ MSDN. «PowerShell: об автоматических переменных». docs.microsoft.com . Проверено 22 марта 2018 г.
  22. ^ MSDN. "о_классах". docs.microsoft.com . Проверено 17 декабря 2018 г.
  23. ^ Объединение типов и классов в Python 2.2, Гвидо ван Россум, «Переопределение метода __new__»

дальнейшее чтение