В чем суть self в ООП языка Python и this в C++ (лучше в примерах)?
question@mail.ru
·
01.01.1970 03:00
Смысл this в C++ / self в Python
answer@mail.ru
·
01.01.1970 03:00
Верно подмечено, что эти понятия имеют одну и ту же роль в ООП, объектно-ориентированном программировании: это отсылка объекта к самому себе. Она позволяет:
- Обращаться к собственным полям (т.е, переменным) и методам;
- Передавать объекту самого себя в другие функции и объекты.
Python и C++ отличаются тем, что первая часть в C++ (ещё в Java, C# и Objective-C) реализована автоматически, нам не обязательно постоянно прописывать self или this. Однако это порождает либо путаницу между переменными объекта и локальными, либо постоянное использование нижнего подчёркивания в названии переменных, что, на мой взгляд, не сильно лучше ссылки на объект. Наоборот, в Питоне (и, например, JavaScript'e) необходимо всегда явно указывать, если обращение идёт к полю текущего объекта.
Рассмотрим оба варианта использования.
1) Для обращения к своим полям
Возьмём класс прямоугольник, у него есть две переменные с длинами сторон: a и b, нам нужен метод для вычисления площади – а для этого нужно обращаться из метода к полям объекта. Код на Python:
class Rect: def __init__(self, a, b): # по наличию или отсутствию self различаются # локальные переменные и поля объекта self.a = a self.b = b # self явно присутствует в аргументах методов def area(self): retu self.a * self.bВ языке C++ для этого есть разные способы. Вариант А:
class Rect { private: int _a, _b; public: Rect(int a, int b) { // нижнее подчёркивание используется для того, чтобы // различать аргументы/локальные переменные // и поля объекта _a = a; _b = b; } int area() { // this нет ни в аргументах метода, // ни в обращении к полям объекта retu _a * _b; }}C++, вариант Б:
class Rect { private: int a, b; public: Rect(int a, int b) : a(a), b (b) { // такой способ инициализации полей объекта // позволяет избегать путаницы с аргументами } int area() { // также, для обращения к собственным переменным // можно использовать this retu this->a * this->b; }}Лирическое отступление
Обратите внимание на то, что в методах на Питоне self всегда указывается явно, а в C++ this принимает значение автоматически. И хотя конструкция применяется одна и та же object.method(data), а в объявлении методов this не используется, на самом деле ссылка на объект присутствует как скрытый первый аргумент. Можно указать объект и явным образом, вот две эквивалентные строки C++ кода:
my_object.push(3);MyClass::push(&my_object, 3);// надеюсь, Вы понимаете C++ значение символов & и *// если нет, спешите скорее разузнатьДля my_object как экземпляра класса такого вида:
class MyClass { ... void push(int number) { ... }}Кстати, подобным образом явно указать объект можно и в Питоне:
# неявная передача объекта в первый аргументmy_object.push(2)# явное указание объекта как аргументаMyClass.push(my_object, 2)2) Для передачи текущего объекта
Например, у нас есть какой-нибудь объект контроллер или контейнер, и объекты нашего класса должны автоматически туда положиться или удалиться из него. Python:
all = []class MyClass: def __init__(self): all.append(self)C++:
class MyClass {public: MyClass();}vector<MyClass*> all = new vector<MyClass*>();MyClass::MyClass() { all.push(this);}