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 , используют . Visual Basicself от Microsoft использует .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, использование thisв коде, хотя и не является незаконным, может вызвать тревогу у программиста по обслуживанию, хотя thisв этом случае все еще существуют допустимые варианты использования , такие как ссылка на переменные экземпляра, скрытые локальными переменными с тем же именем, или если метод хочет вернуть ссылку на текущий объект, т. е this. на себя.

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

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

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

использовать функцию ":5.16" ; sub { my $x = shift ; $x == 0 ? 1 : $x * __SUB__ -> ( $x - 1 ); }                    

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

беззнаковый факториал целого числа ( беззнаковый факториал n ) { если ( n == 0 ) вернуть 1 ; иначе вернуть n * это -> факториал ( n - 1 ); }                 

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

Проблема хрупкого базового класса была возложена на открытую рекурсию, с предположением, что вызов методов по thisумолчанию в закрытой рекурсии (статическая диспетчеризация) вместо открытой рекурсии (динамическая диспетчеризация), используя открытую рекурсию только тогда, когда это специально запрошено; внешние вызовы (не использующие this) будут динамически диспетчеризироваться как обычно. [6] [7] Способ, которым это решается на практике в JDK, заключается в определенной дисциплине программирования; эта дисциплина была формализована C. Ruby и GT Leavens; она состоит из следующих правил: [8]

Реализации

С++

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

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

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

С#

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

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

Д

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

Дилан

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

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

и

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

Эйфелева

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

 сорт МОЙ_КЛАСС  особенность -- Доступ   foo : ЦЕЛОЕ ЧИСЛО   my_function : ЦЕЛОЕ ЧИСЛО  делать Результат := foo   конец  конец

[12]

В строке № 10 (выше) подразумевается ссылка на Currentвызов простого `foo'.

В строке № 10 (ниже) имеется явная ссылка на Currentвызов `Current.foo'.

 сорт МОЙ_КЛАСС  особенность -- Доступ   foo : ЦЕЛОЕ ЧИСЛО   my_function : ЦЕЛОЕ ЧИСЛО  делать Результат := Текущий . foo   конец  конец

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

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

 сорт МОЙ_КЛАСС  особенность -- Доступ   моя_команда -- Создать MY_OTHER_CLASS с `Current' местный х : МОЙ_ДРУГОЙ_КЛАСС  делать создать x . 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 () { // Здесь и this, и that указывают на элемент под курсором мыши. var that = this ; $ ( this ) .find ( '.elements' ) .each ( function () { // Здесь this указывает на перебираемый элемент DOM. // Однако that по-прежнему указывает на элемент под курсором мыши. $ ( this ) .addClass ( "highlight" ); }); });             

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

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

Луа

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

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

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

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

PowerShell

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

"один" ,  "два" ,  "три"  |  %  {  write $_  }

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

Питон

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

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

Ржавчина

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

структура  Foo { bar : i32 , }  impl Foo { fn new () -> Foo { Foo { bar : 0 , } } fn refer ( & self ) { println! ( " { } " , self.bar ) ; } fn mutate ( & mut self , baz : i32 ) { self.bar = baz ; } fn consumer ( self ) { self.refer ( ) ; } }                               

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

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

Себя

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

Xbase++

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

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

Ссылки

  1. ^ Даль, Оле-Йохан ; Мирхауг, Бьёрн; Найгаард, Кристен (1970). «Общий базовый язык, Норвежский вычислительный центр».
  2. ^ Powell, Thomas A, и Schneider, Fritz, 2012. JavaScript: Полный справочник, Третье издание. McGraw-Hill. Глава 11, Обработка событий , стр. 428. ISBN 978-0-07-174120-0 
  3. ^ Использование коллекции компиляторов GNU (GCC) – Связанные функции-члены
  4. ^ «Закрытая и открытая рекурсия», Ральф Хинце, июль 2007 г.
  5. ^ Открытая рекурсия, Лямбда-конечная
  6. ^ «Избирательная открытая рекурсия: решение проблемы хрупкого базового класса», Джонатан Олдрич
  7. ^ «Избирательная открытая рекурсия: решение проблемы хрупкого базового класса», Lambda the Ultimate
  8. ^ Aldrich, Jonathan, and Kevin Donnelly. "Selective open recursion: Modular reasoning about components and heritage". SAVCBS 2004 Specification and Verification of Component-Based Systems (2004): 26. цитирование решения, принятого в JDK C. Ruby и GT Leavens. "Safely Creating Correct Subclasses without Seeing Superclass Code". В Object-Oriented Programming Systems, Languages, and Applications, October 2000. doi :10.1145/353171.353186 также доступно как технический отчет TR #00-05d
  9. ^ ISO/IEC 14882:2003(E): Языки программирования - C++ . ISO/IEC. 2003.
  10. ^ Страуструп: Часто задаваемые вопросы о стиле и технике C++
  11. ^ Де Смет, Барт, 2011. C# 4.0 Unleashed. Sams Publishing, Индианаполис, США. Глава 4, Language Essentials , стр. 210. ISBN 978-0-672-33079-7 
  12. ^ ПРИМЕЧАНИЕ: Номера строк приведены только для справочных целей. В тексте класса Eiffel нет номеров строк. Однако в среде разработки Eiffel Studio есть опция нумерации строк, которую можно включить для справочных целей (например, парное программирование и т. д.).
  13. ^ Barnes, D. и Kölling, M. Objects First with Java . "...причина использования этой конструкции [this] заключается в том, что у нас есть ситуация, известная как перегрузка имен — одно и то же имя используется для двух разных сущностей... Важно понимать, что поля и параметры — это отдельные переменные, которые существуют независимо друг от друга, даже если они имеют похожие имена. Параметр и поле, имеющие одно и то же имя, не являются проблемой в Java". [ требуется цитата ]
  14. ^ Крокфорд, Дуглас, 2008. JavaScript: The Good Parts . O'Reilly Media Inc. и Yahoo! Inc. Глава 4, Функции , стр. 28. ISBN 978-0-596-51774-8 
  15. ^ Powell, Thomas A, и Schneider, Fritz, 2012. JavaScript: Полный справочник, Третье издание. McGraw-Hill. Глава 5, Функции , стр. 170–1. ISBN 978-0-07-174120-0 
  16. ^ Goodman, Danny, with Morrison, Michael, 2004. JavaScript Bible, 5-е издание. Wiley Publishing, Inc., Индианаполис, США. Глава 33, Функции и пользовательские объекты , стр. 987. ISBN 0-7645-5743-2 
  17. ^ Сеть разработчиков Mozilla: Window.self
  18. ^ Сеть разработчиков Mozilla: API Web Worker
  19. ^ Сеть разработчиков Mozilla: globalThis
  20. ^ "Программирование на Lua: 16".
  21. ^ msdn. "PowerShell: Об автоматических переменных". docs.microsoft.com . Получено 22.03.2018 .
  22. ^ msdn. "about_Classes". docs.microsoft.com . Получено 2018-12-17 .
  23. ^ Унификация типов и классов в Python 2.2, Гвидо ван Россум, «Переопределение метода __new__»

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