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, this
or 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 { мой $ x = сдвиг ; $ x == 0 ? 1 : $ x * __SUB__ -> ( $ x - 1 ); }
Напротив, в C ++ (с использованием явного указания this
для ясности, хотя и не обязательно) this
привязка к самому объекту, но если метод класса был объявлен «виртуальным», то есть полиморфным в базе, он разрешается через динамическую отправку ( позднее связывание ), так что производные классы могут его переопределить.
unsigned int factorial ( unsigned int n ) { если ( n == 0 ) возврат 1 ; иначе верните n * this -> factorial ( n - 1 ); }
Этот пример является искусственным, так как это прямая рекурсия, поэтому переопределение factorial
метода переопределит эту функцию; более естественными примерами являются случаи, когда метод в производном классе вызывает тот же метод в базовом классе, или в случаях взаимной рекурсии. [4] [5]
Проблема хрупкого базового класса была возложена на открытую рекурсию с предложением вызывать методы по this
умолчанию для закрытой рекурсии (статическая отправка, раннее связывание), а не для открытой рекурсии (динамическая отправка, позднее связывание), только с использованием открытой рекурсии, когда это специально запрошено; внешние вызовы (не использующиеся this
) будут отправляться динамически, как обычно. [6] [7] На практике это решается в JDK с помощью определенной дисциплины программиста; эта дисциплина была формализована К. Руби и Г. Т. Ливенсом; в основном он состоит из следующих правил: [8]
- Никакой код не вызывает
public
методы дляthis
. - Код, который можно повторно использовать внутри компании (путем вызова из других методов того же класса), инкапсулируется в метод
protected
илиprivate
; если он также должен быть открыт непосредственно для пользователей, тоpublic
метод- оболочка вызывает внутренний метод. - Предыдущая рекомендация может быть ослаблена для чистых методов.
Реализации
C ++
Ранние версии C ++ позволяли this
изменять указатель; таким образом программист мог изменить объект, над которым работает метод. В конечном итоге эта функция была удалена, и теперь this
в C ++ используется r-значение . [9]
Ранние версии C ++ не включали ссылки, и было высказано предположение, что если бы они были таковыми в C ++ с самого начала, this
они были бы ссылкой, а не указателем. [10]
C ++ позволяет объекты уничтожить себя с утверждением исходного кода: delete this
.
C #
Ключевое слово this
в C # работает так же, как в Java, для ссылочных типов. Однако, в пределах # C типов значений , this
имеет совершенно разную семантику, подобны обычной изменяемую ссылку переменной, и даже может произойти на левую часть присваивания.
Одно из применений this
в C # - разрешить ссылку на переменную внешнего поля в методе, который содержит локальную переменную с тем же именем. В такой ситуации, например, оператор var n = localAndFieldname;
в методе назначит тип и значение локальных переменного localAndFieldname
к n
, в то время как оператор var n = this.localAndFieldname;
будет присвоить тип и значение внешнего переменного поля к n
. [11]
D
В D this
в классе метод структуры или объединения относится к неизменяемой ссылке на экземпляр включающего агрегата. Классы - это ссылочные типы, структуры и объединения - это типы значений. В первой версии D ключевое слово this
используется как указатель на экземпляр объекта, к которому привязан метод, тогда как в D2 оно имеет символ неявного refаргумента функции.
Дилан
В языке программирования Dylan , который является объектно-ориентированным языком, который поддерживает мультиметоды и не имеет понятия this
, отправка сообщения объекту по-прежнему сохраняется в синтаксисе. Две формы ниже работают одинаково; различия - всего лишь синтаксический сахар .
объект.method (параметр1, параметр2)
а также
метод (объект, параметр1, параметр2)
Эйфелева
В тексте класса текущий тип - это тип, полученный из текущего класса . В функциях (подпрограммах, командах и запросах) класса можно использовать ключевое слово Current
для ссылки на текущий класс и его функции. Использование ключевого слова не Current
является обязательным, поскольку ключевое слово Current
подразумевается простой ссылкой на имя текущего объекта класса открыто. Например: у кого-то может быть функция `foo 'в классе MY_CLASS и ссылаться на нее следующим образом:
класс МОИ ЗАНЯТИЯ особенность - Доступ foo : INTEGER моя_функция : ЦЕЛОЕ делать Результат : = foo конец конец
[12]
Строка № 10 (выше) подразумевает ссылку Current
на вызов простого `foo '.
Строка № 10 (ниже) имеет явную ссылку Current
на вызов `Current.foo '.
класс МОИ ЗАНЯТИЯ особенность - Доступ foo : INTEGER моя_функция : ЦЕЛОЕ делать Результат : = Текущий . фу конец конец
Любой подход приемлем для компилятора, но подразумеваемая версия (например x := foo
) предпочтительнее, поскольку она менее подробна.
Как и в случае с другими языками, бывают случаи, когда использование ключевого слова Current
обязательно, например:
класс МОИ ЗАНЯТИЯ особенность - Доступ моя_команда - Создать MY_OTHER_CLASS с помощью `Current ' местный x : MY_OTHER_CLASS делать создать x . make_with_something ( Текущий ) конец конец
В случае приведенного выше кода вызов make_with_something в строке # 11 передает текущий класс путем явной передачи ключевого слова Current
.
Ява
Ключевое слово this
- это ключевое слово языка Java , представляющее текущий экземпляр класса, в котором оно появляется. Он используется для доступа к переменным и методам класса.
Поскольку все методы экземпляра в Java виртуальны, this
они никогда не могут иметь значение NULL. [13]
JavaScript
В JavaScript, который представляет собой язык программирования или сценариев, широко используемый в веб-браузерах, this
является важным ключевым словом, хотя его оценка зависит от того, где он используется.
- При использовании вне какой-либо функции в глобальном пространстве
this
относится к охватывающему объекту, которым в данном случае является закрывающее окно браузера,window
объект. - При использовании в функции, определенной в глобальном пространстве, то, на что
this
ссылается ключевое слово, зависит от того, как функция вызывается. Когда такая функция вызывается напрямую (напримерf(x)
), онаthis
будет обращаться к глобальному пространству, в котором функция определена, и в котором также могут существовать другие глобальные функции и переменные (или в строгом режиме, это такundefined
). Однако, если глобальная содержащаяся функцияthis
вызывается как часть обработчика событий элемента в объекте документа, онаthis
будет ссылаться на вызывающий элемент HTML. - Когда метод вызывается с использованием
new
ключевого слова (напримерvar c = new Thing()
), тогда внутри Thingthis
ссылается на сам объект Thing. - Когда функция прикрепляется как свойство объекта и вызывается как метод этого объекта (например
obj.f(x)
),this
будет ссылаться на объект, внутри которого содержится функция. [14] [15] Можно даже указать вручнуюthis
при вызове функции, используя методы.call()
или.apply()
объекта функции. [16] Например, вызов методаobj.f(x)
также может быть записан какobj.f.call(obj, x)
.
Чтобы обойти различное значение this
вложенных функций, таких как обработчики событий DOM, в JavaScript является распространенной идиомой сохранять this
ссылку на вызывающий объект в переменной (обычно называемой that
или self
), а затем использовать эту переменную для ссылки на вызывающий объект. объект во вложенных функциях.
Например:
// В этом примере $ - это ссылка на библиотеку jQuery $ ( ".element" ). hover ( function () { // Здесь и то, и то указывают на элемент под курсором мыши. var that = this ; $ ( это ). найти ( '.элементы' ). each ( function () { // Здесь это указывает на повторяемый элемент DOM. // Однако это все еще указывает на элемент под курсором мыши. $ ( this ). addClass ( "highlight" ); }); });
Lua
В Lua self
создается как синтаксический сахар, когда функции определяются с помощью :
оператора. [17] При вызове метода с использованием :
индексируемый объект будет неявно передан в качестве первого аргумента вызываемой функции.
Например, следующие две функции эквивалентны:
local obj = {}функция obj . foo ( arg1 , arg2 ) print ( arg1 , arg2 ) - здесь нельзя использовать "self" конецfunction obj : bar ( arg ) print ( self , arg ) - "self" - неявный первый аргумент перед концом arg- Все функции могут быть вызваны обоими способами с помощью символа "." или с ":"obj : foo ( "Foo" ) - эквивалент obj.foo (obj, "Foo") obj . bar ( obj , «Бар» ) - эквивалент obj: bar («Бар»)
Сам Lua не является объектно-ориентированным, но в сочетании с другой функцией, называемой метатаблицами, использование self
позволяет программистам определять функции аналогично объектно-ориентированному программированию.
PowerShell
В PowerShell специальная автоматическая переменная $_
содержит текущий объект в объекте конвейера. Вы можете использовать эту переменную в командах, которые выполняют действие над каждым объектом или над выбранными объектами в конвейере. [18]
«один» , «два» , «три» | % { write $ _ }
Также начиная с PowerShell 5.0, который добавляет формальный синтаксис для определения классов и других определяемых пользователем типов, переменная [19] $this
описывает текущий экземпляр объекта.
Python
В Python нет ключевого слова для this
. Когда функция-член вызывается для объекта, она вызывает функцию-член с тем же именем для объекта класса объекта, при этом объект автоматически связывается с первым аргументом функции. Таким образом, обязательный первый параметр методов экземпляра служит this
; этот параметр имеет условное название self
, но может называться как угодно.
В методах класса (созданных с помощью classmethod
декоратора) первый аргумент относится к самому объекту класса и обычно называется cls
; они в основном используются для наследуемых конструкторов [20], где использование класса в качестве параметра позволяет создать подкласс конструктора. В статических методах (созданных с помощью staticmethod
декоратора) не существует специального первого аргумента.
Ржавчина
В Rust типы объявляются отдельно от связанных с ними функций. Функции, разработанные как аналог методов экземпляра в более традиционно объектно-ориентированных языках, должны явно принимать в self
качестве своего первого параметра. Затем эти функции могут быть вызваны с использованием instance.method()
синтаксического сахара. Например:
struct Foo { бар : i32 ,}impl Foo { fn new () -> Foo { Фу { bar : 0 , } } fn refer ( & self ) { println! ( "{}" , self . bar ); } fn mutate ( & mut self , baz : i32 ) { я . bar = baz ; } fn consumer ( self ) { я . ссылаться (); }}
Это определяет тип, с Foo
которым связаны четыре функции. Первая, Foo::new()
не является функцией экземпляра и должна быть указана с префиксом типа. Остальные три все принимают self
параметр различными способами и могут быть вызваны в Foo
экземпляре с использованием синтаксического сахара с точечной нотацией, что эквивалентно вызову имени функции с указанием типа с явным self
первым параметром.
пусть foo = Foo :: new (); // должна вызываться как функция указанного типа foo . ссылаться (); // выводит "0". Foo :: refer () имеет доступ только для чтения к экземпляру foo foo . мутировать ( 5 ); // изменяет foo на место, разрешенное спецификацией & mut foo . потреблять (); // выводит "5" и уничтожает foo, так как Foo :: consumer () полностью владеет собой // эквивалент foo.refer () Foo :: refer ( foo ); // ошибка компиляции: foo выходит за рамки
Себя
Язык Я назван в честь этого использования слова «я».
Xbase ++
Self
строго используется в методах класса. Другой способ сослаться Self
на использование ::
.
Смотрите также
- Анонимная рекурсия - рекурсия без вызова функции по имени
- Наследование (объектно-ориентированное программирование) - механизм базирования объекта или класса на другом объекте или классе, сохраняющем аналогичную реализацию.
- Самореференция - предложение, идея или формула, относящиеся к самому себе.
- Шизофрения (объектно-ориентированное программирование) - осложнение, возникающее из-за делегирования и связанных с ним методов в объектно-ориентированном программировании.
- Префикс сегмента программы - структура данных в DOS
Рекомендации
- ^ Даль, Оле-Йохан ; Myhrhaug, Bjørn; Найгаард, Кристен (1970). «Общий базовый язык, Норвежский вычислительный центр» .
- ^ Пауэлл, Томас А. и Шнайдер, Фриц, 2012. JavaScript: Полный справочник, третье издание. Макгроу-Хилл. Глава 11, Обработка событий , стр. 428. ISBN 978-0-07-174120-0
- ^ Использование GNU Compiler Collection (GCC) - Связанные функции-члены
- ^ " Закрытая и открытая рекурсия ", Ральф Хинце , июль 2007 г.
- ^ Открытая рекурсия , Lambda the Ultimate
- ^ " Селективная открытая рекурсия: решение проблемы хрупкого базового класса ", Джонатан Олдрич
- ^ « Селективная открытая рекурсия: решение проблемы хрупкого базового класса », Lambda the Ultimate
- ↑ Олдрич, Джонатан и Кевин Доннелли. « Избирательная открытая рекурсия: модульные рассуждения о компонентах и наследовании». SAVCBS 2004 Specification and Verification of Component-Based Systems (2004): 26. со ссылкой на решение, принятое в JDK, C. Ruby и GT Leavens. «Безопасное создание правильных подклассов без просмотра кода суперкласса». В «Системах, языках и приложениях объектно-ориентированного программирования», октябрь 2000 г. doi : 10.1145 / 353171.353186 также доступен как технический отчет TR # 00-05d
- ^ ISO / IEC 14882: 2003 (E): Языки программирования - C ++ . ИСО / МЭК. 2003 г.
- ^ Страуструп: FAQ по стилю и технике C ++
- ^ Де Смет, Барт, 2011. C # 4.0 Unleashed. Sams Publishing, Индианаполис, США. Глава 4, Основы языка , стр. 210. ISBN 978-0-672-33079-7
- ^ ПРИМЕЧАНИЕ. Номера строк приведены только для справки. У Эйфеля нет номеров строк в тексте класса. Однако в Eiffel Studio IDE есть опция номера строки, которую можно дополнительно включить для справочных целей (например, парное программирование и т. Д.).
- ^ Барнс, Д. и Келлинг, М. Объекты - первые с Java . «... причина использования этой конструкции [this] в том, что у нас есть ситуация, известная как перегрузка имени - одно и то же имя используется для двух разных сущностей ... Важно понимать, что поля и параметры являются отдельные переменные, которые существуют независимо друг от друга, даже если у них одинаковые имена. Параметр и поле с одинаковым именем на самом деле не проблема в Java ». [ необходима цитата ]
- ^ Крокфорд, Douglas, 2008. JavaScript: The Good Parts . O'Reilly Media Inc. и Yahoo! Inc. Глава 4, Функции , стр. 28. ISBN 978-0-596-51774-8
- ^ Пауэлл, Томас А. и Шнайдер, Фриц, 2012. JavaScript: Полный справочник, третье издание. Макгроу-Хилл. Глава 5, Функции , стр. 170–1. ISBN 978-0-07-174120-0
- ^ Гудман, Дэнни, с Моррисоном, Майклом, 2004. Библия JavaScript, 5-е издание. Wiley Publishing, Inc., Индианаполис, США. Глава 33, Функции и пользовательские объекты , стр. 987. ISBN 0-7645-5743-2
- ^ https://www.lua.org/pil/16.html
- ^ msdn. «PowerShell: об автоматических переменных» . docs.microsoft.com . Проверено 22 марта 2018 .
- ^ msdn. «about_Classes» . docs.microsoft.com . Проверено 17 декабря 2018 .
- ^ Объединение типов и классов в Python 2.2, Гвидо ван Россум, « Переопределение метода __new__ »
дальнейшее чтение
- Мейерс, Скотт, 1995. Более эффективный C ++: 35 новых способов улучшить ваши программы и конструкции . ISBN 0-201-63371-X Скотт Мейерс
- Страуструп, Бьярн, 1994. Дизайн и эволюция C ++ . Аддисон-Уэсли Паб. Co. ISBN 0-201-54330-3 Бьярн Страуструп