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
, использование this
in в коде, хотя и не является незаконным, может вызвать тревогу у программиста сопровождения, хотя в этом случае все еще существуют законные варианты использования 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]
public
методы в this
.protected
или private
; если его также необходимо предоставить непосредственно пользователям, то public
метод-оболочка вызывает внутренний метод.Ранние версии C++ позволяли this
изменять указатель; таким образом программист мог изменить объект, над которым работал метод. Эта функция со временем была удалена, и теперь this
в C++ используется r-значение . [9]
Ранние версии C++ не включали ссылки, и было высказано предположение, что если бы они были такими в C++ с самого начала, this
они были бы ссылкой, а не указателем. [10]
C++ позволяет объектам уничтожать себя с помощью оператора исходного кода: delete this
.
Ключевое слово this
в C# работает для ссылочных типов так же, как и в Java. Однако в типах значений C# оно this
имеет совершенно другую семантику, оно похоже на обычную ссылку на изменяемую переменную и может даже встречаться в левой части присваивания.
Одним из вариантов использования this
в C# является разрешение ссылки на переменную внешнего поля внутри метода, который содержит локальную переменную с тем же именем. В такой ситуации, например, оператор внутри метода присваивает var n = localAndFieldname;
тип и значение локальной переменной , тогда как оператор присваивает тип и значение переменной внешнего поля . [11]localAndFieldname
n
var 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, который представляет собой язык программирования или сценариев, широко используемый в веб-браузерах, this
является важным ключевым словом, хотя то, что оно оценивает, зависит от того, где оно используется.
this
относится к включающему объекту, которым в данном случае является включающее окно браузера, объект window
.this
на что ссылается ключевое слово, зависит от того, как вызывается функция. Когда такая функция вызывается напрямую (например, f(x)
), this
она будет ссылаться обратно на глобальное пространство, в котором определена функция, и в котором также могут существовать другие глобальные функции и переменные (или в строгом режиме, это так и есть undefined
). Однако если глобальная функция, содержащая объект, this
вызывается как часть обработчика событий элемента в объекте документа, this
она будет ссылаться на вызывающий элемент HTML.new
ключевого слова (например var c = new Thing()
, ), то внутри Thing this
ссылается на сам объект 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 ; $ ( 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 специальная автоматическая переменная $_
содержит текущий объект в объекте конвейера. Эту переменную можно использовать в командах, которые выполняют действие над каждым объектом или над выбранными объектами в конвейере. [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».
Self
используется строго внутри методов класса. Другой способ ссылки Self
— использовать ::
.