это (компьютерное программирование)
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
в коде, хотя и не является незаконным, может стать сигналом тревоги для программиста по сопровождению, хотя все еще существуют законные варианты использования this
в этом случае, например, ссылка на переменные экземпляра, скрытые локальными переменными с тем же именем, или если метод хочет вернуть ссылку на текущий объект, т.е. this
, сам.
В некоторых компиляторах (например, GCC ) указатели на методы экземпляра C++ могут быть напрямую приведены к указателю другого типа с явным this
параметр указателя. [3]
Открытая рекурсия
[ редактировать ]Семантика отправки this
, а именно этот метод вызывает this
динамически отправляются, называется открытой рекурсией и означает, что эти методы могут быть переопределены производными классами или объектами. Напротив, прямая именованная рекурсия или анонимная рекурсия функции использует закрытую рекурсию с ранним связыванием. Например, в следующем коде Perl для факториала токен __SUB__
является ссылкой на текущую функцию:
use feature ":5.16";
sub {
my $x = shift;
$x == 0 ? 1 : $x * __SUB__->( $x - 1 );
}
Напротив, в C++ (с использованием явного this
для ясности, хотя и не обязательно) this
привязывается к самому объекту, но если метод класса был объявлен «виртуальным», то есть полиморфным в базе, он разрешается посредством динамической отправки ( позднего связывания ), чтобы производные классы могли его переопределить.
unsigned int factorial(unsigned int n)
{
if (n == 0)
return 1;
else
return n * this->factorial(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;
внутри метода будет присвоен тип и значение локальной переменной localAndFieldname
к n
, тогда как утверждение var n = this.localAndFieldname;
назначит тип и значение переменной внешнего поля n
. [11]
Д
[ редактировать ]В Д this
в методе класса, структуры или объединения относится к неизменяемой ссылке на экземпляр включающего агрегата. Классы являются ссылочными типами, а структуры и объединения — типами значений. В первой версии D ключевое слово this
используется как указатель на экземпляр объекта, к которому привязан метод, тогда как в D2 он имеет характер неявного ref
аргумент функции.
Дилан
[ редактировать ]В языке программирования Dylan , который является объектно-ориентированным языком, поддерживающим мультиметоды и не имеющим понятия this
, отправка сообщения объекту по-прежнему сохраняется в синтаксисе. Две формы ниже работают одинаково; различия — всего лишь синтаксический сахар .
object.method(param1, param2)
и
method (object, param1, param2)
Эйфелева
[ редактировать ]В тексте класса текущий тип — это тип, полученный из текущего класса . Внутри функций (подпрограмм, команд и запросов) класса можно использовать ключевое слово Current
для ссылки на текущий класс и его функции. Использование ключевого слова Current
является необязательным в качестве ключевого слова Current
подразумевается путем простого открытого обращения к имени текущего объекта класса. Например: в классе MY_CLASS может быть функция `foo', и обращаться к ней можно так:
class
MY_CLASS
feature -- Access
foo: INTEGER
my_function: INTEGER
do
Result := foo
end
end
Строка № 10 (выше) содержит подразумеваемую ссылку на Current
вызовом простой `foo'.
Строка № 10 (ниже) содержит явную ссылку на Current
вызовом Current.foo.
class
MY_CLASS
feature -- Access
foo: INTEGER
my_function: INTEGER
do
Result := Current.foo
end
end
Любой подход приемлем для компилятора, но подразумеваемая версия (например, x := foo
) предпочтительнее, поскольку он менее многословен.
Как и в других языках, бывают случаи, когда использование ключевого слова Current
является обязательным, например:
class
MY_CLASS
feature -- Access
my_command
-- Create MY_OTHER_CLASS with `Current'
local
x: MY_OTHER_CLASS
do
create x.make_with_something (Current)
end
end
В случае приведенного выше кода вызов make_with_something в строке № 11 передает текущий класс путем явной передачи ключевого слова Current
.
Ява
[ редактировать ]Ключевое слово this
— это ключевое слово языка Java , которое представляет текущий экземпляр класса, в котором оно встречается. Он используется для доступа к переменным и методам класса.
Поскольку все методы экземпляра в Java виртуальны, this
никогда не может быть нулевым. [13]
JavaScript
[ редактировать ]В JavaScript, который представляет собой язык программирования или сценариев, широко используемый в веб-браузерах, this
— важное ключевое слово, хотя его значение зависит от того, где оно используется.
- При использовании вне какой-либо функции в глобальном пространстве
this
ссылается на включающий объект, которым в данном случае является включающее окно браузера,window
объект. - При использовании в функции, определенной в глобальном пространстве, какое ключевое слово
this
ссылается на зависит от того, как вызывается функция. Когда такая функция вызывается напрямую (например,f(x)
),this
будет ссылаться на глобальное пространство, в котором определена функция и в котором также могут существовать другие глобальные функции и переменные (или в строгом режиме, этоundefined
). Если глобальная функция, содержащаяthis
вызывается как часть обработчика событий элемента объекта документа, однакоthis
будет ссылаться на вызывающий элемент HTML. - Когда метод вызывается с использованием
new
ключевое слово (напримерvar c = new 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
), а затем используйте переменную для ссылки на вызывающий объект во вложенных функциях.
Например:
// In this example $ is a reference to the jQuery library
$(".element").hover(function() {
// Here, both this and that point to the element under the mouse cursor.
var that = this;
$(this).find('.elements').each(function() {
// Here, this points to the DOM element being iterated.
// However, that still points to the element under the mouse cursor.
$(this).addClass("highlight");
});
});
Примечательно, что JavaScript использует оба this
и соответствующее ключевое слово self
[17] (в отличие от большинства других языков, которые, как правило, используют тот или иной), с self
ограничивается специально веб-работниками. [18]
Наконец, в качестве надежного способа конкретной ссылки на глобальный объект (окно или его эквивалент) в JavaScript реализована функция globalThis
ключевое слово. [19]
Два
[ редактировать ]В Луа, self
создается как синтаксический сахар , когда функции определяются с использованием :
оператор. [20] При вызове метода с использованием :
, индексируемый объект будет неявно указан в качестве первого аргумента вызываемой функции.
Например, следующие две функции эквивалентны:
local obj = {}
function obj.foo(arg1, arg2)
print(arg1, arg2) -- cannot use "self" here
end
function obj:bar(arg)
print(self, arg) -- "self" is an implicit first argument before arg
end
-- All functions can be invoked both ways, with "." or with ":"
obj:foo("Foo") -- equivalent to obj.foo(obj, "Foo")
obj.bar(obj, "Bar") -- equivalent to obj:bar("Bar")
Lua сам по себе не является объектно-ориентированным, но в сочетании с другой функцией, называемой метатаблицами, использование self
позволяет программистам определять функции способом, напоминающим объектно-ориентированное программирование.
PowerShell
[ редактировать ]В PowerShell специальная автоматическая переменная $_
содержит текущий объект в объекте конвейера. Эту переменную можно использовать в командах, которые выполняют действие над каждым объектом или над выбранными объектами в конвейере. [21]
"one", "two", "three" | % { write $_ }
Также начиная с PowerShell 5.0, в котором добавлен формальный синтаксис для определения классов и других определяемых пользователем типов. [22] $this
Переменная описывает текущий экземпляр объекта.
Питон
[ редактировать ]В Python нет ключевого слова для this
. Когда функция-член вызывается для объекта, она вызывает функцию-член с тем же именем в объекте класса объекта, при этом объект автоматически привязывается к первому аргументу функции. Таким образом, обязательным первым параметром методов экземпляра служит this
; этот параметр условно назван self
, но можно назвать как угодно.
В методах класса (созданных с помощью classmethod
декоратор), первый аргумент относится к самому объекту класса и обычно называется cls
; они в основном используются для наследуемых конструкторов, [23] где использование класса в качестве параметра позволяет создать подкласс конструктора. В статических методах (созданных с помощью staticmethod
декоратор), специального первого аргумента не существует.
Ржавчина
[ редактировать ]В Rust типы объявляются отдельно от связанных с ними функций. Функции, аналогичные методам экземпляров в более традиционных объектно-ориентированных языках, должны явно принимать self
в качестве их первого параметра. Эти функции затем можно вызвать с помощью instance.method()
синтаксический сахар. Например:
struct 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 consume(self) {
self.refer();
}
}
Это определяет тип, Foo
, который имеет четыре связанные функции. Первый, Foo::new()
, не является функцией экземпляра и должен быть указан с префиксом типа. Оставшиеся трое занимают self
параметр различными способами и может быть вызван на Foo
экземпляр с использованием синтаксиса точечной нотации, который эквивалентен вызову имени функции с указанием типа с явным self
первый параметр.
let mut foo = Foo::new(); // must called as a type-specified function
foo.refer(); // prints "0". Foo::refer() has read-only access to the foo instance
foo.mutate(5); // mutates foo in place, permitted by the &mut specification, need foo to be declared mut
foo.consume(); // prints "5" and destroys foo, as Foo::consume() takes full ownership of self
// equivalent to foo.refer()
Foo::refer(foo); // compilation error: foo is out of scope
Себя
[ редактировать ]Язык Self назван в честь этого использования слова «self».
Xbase++
[ редактировать ]Self
используется строго внутри методов класса.
Еще один способ обратиться к Self
это использовать ::
.
См. также
[ редактировать ]- Анонимная рекурсия — рекурсия без вызова функции по имени.
- Наследование (объектно-ориентированное программирование) — процесс получения классов из иерархии и их организации.
- Самореференция - предложение, идея или формула, которая ссылается на себя.
- Шизофрения (объектно-ориентированное программирование) - осложнение, возникающее в результате делегирования и связанных с ним методов объектно-ориентированного программирования.
- Префикс сегмента программы - структура данных в DOS.
Ссылки
[ редактировать ]- ^ Даль, Оле-Йохан ; Мирхауг, Бьёрн; Найгаард, Кристен (1970). «Общий базовый язык, Норвежский вычислительный центр» .
- ^ Пауэлл, Томас А., и Шнайдер, Фриц, 2012. JavaScript: Полный справочник, третье издание. МакГроу-Хилл. Глава 11, Обработка событий , стр. 428. ISBN 978-0-07-174120-0
- ^ Использование коллекции компиляторов GNU (GCC) — привязанные функции-члены.
- ^ « Закрытая и открытая рекурсия », Ральф Хинце , июль 2007 г.
- ^ Открытая рекурсия , Lambda the Ultimate
- ^ « Выборочная открытая рекурсия: решение проблемы хрупкого базового класса », Джонатан Олдрич
- ^ « Выборочная открытая рекурсия: решение проблемы хрупкого базового класса », Lambda the Ultimate
- ^ Олдрич, Джонатан и Кевин Доннелли. « Выборочная открытая рекурсия: модульные рассуждения о компонентах и наследовании ». SAVCBS 2004 Спецификация и проверка компонентно-ориентированных систем (2004): 26. со ссылкой на решение, принятое в JDK, C. Ruby и GT Leavens. «Безопасное создание правильных подклассов, не видя кода суперкласса». В «Системах объектно-ориентированного программирования, языках и приложениях», октябрь 2000 г. doi : 10.1145/353171.353186 также доступен в виде технического отчета TR № 00-05d.
- ^ ISO/IEC 14882:2003(E): Языки программирования — C++ . ИСО/МЭК. 2003.
- ^ Страуструп: Часто задаваемые вопросы по стилю и технике C++
- ^ Де Смет, Барт, 2011. C# 4.0 выпущен на свободу. Издательство Sams, Индианаполис, США. Глава 4, Основы языка , стр. 210. ISBN 978-0-672-33079-7
- ^ ПРИМЕЧАНИЕ. Номера строк предназначены только для справочных целей. У Eiffel нет номеров строк в тексте класса. Однако в Eiffel Studio IDE есть опция номера строки, которую можно дополнительно включить для справочных целей (например, парное программирование и т. д.).
- ^ Барнс, Д. и Кёллинг, М. Сначала объекты с Java . «...причина использования этой конструкции [this] заключается в том, что мы имеем ситуацию, известную как перегрузка имени : одно и то же имя используется для двух разных объектов... Важно понимать, что поля и параметры отдельные переменные, которые существуют независимо друг от друга, даже если они имеют одинаковые имена. Параметр и поле, имеющие одно и то же имя, не являются проблемой в Java». [ нужна ссылка ]
- ^ Крокфорд, Дуглас, 2008. JavaScript: хорошие стороны . 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
- ^ Сеть разработчиков Mozilla : Window.self
- ^ Сеть разработчиков Mozilla : API веб-работников
- ^ Сеть разработчиков Mozilla : globalThis
- ^ «Программирование на Lua: 16» .
- ^ MSDN. «PowerShell: об автоматических переменных» . docs.microsoft.com . Проверено 22 марта 2018 г.
- ^ MSDN. "о_классах" . docs.microsoft.com . Проверено 17 декабря 2018 г.
- ^ Объединение типов и классов в Python 2.2, Гвидо ван Россум, « Переопределение метода __new__ »
Дальнейшее чтение
[ редактировать ]- Мейерс, Скотт, 1995. Более эффективный C++: 35 новых способов улучшения ваших программ и проектов . ISBN 0-201-63371-X Скотт Мейерс
- Страуструп, Бьерн, 1994. Дизайн и эволюция C++ . Паб Аддисон-Уэсли. Ко. ISBN 0-201-54330-3 Бьерн Страуструп