Методы-расширения и обратные методы-расширения

В обычном ООП принята простая концепция: нестатический метод класса имеет дополнительный аргумент, указывающий на объект класса, от которого вызывается метод.
Это удобный способ связывания метода с объектом класса. В некоторых языках, например в C#, ввели так называемые методы-расширения: можно объявить обычную "глобальную функцию" (в C# - статический метод другого класса), первый аргумет которой (имеющий некоторый тип Foo) помечается ключевым словом this. Такую функцию можно вызывать как метод класса Foo.
Данная возможность имеет интересные расширения, которые мы и рассмотрим.
Итак, есть класс Foo.
class Foo { 
public def func() {}
};
Метод расширения будет выглядеть так:
def ext_func(this Foo f, int arg) { func(); } 
Внутри метода расширения можно обращаться к нестатическим методам расширямого класса, так как они уже доступны через неявную ссылку this (хотя никто не мешает обращаться к ним и непосредственно через имя объекта f).

Вполне логично предположить, что методы-расширения должны иметь доступ только к публичным полям класса (тогда не будет нарушаться концепция инкапсуляции). Если метод-расширение должен получить доступ к приватным членам класса, то придется объявлять его дружественным в самом классе. В этом смысле методы-расширения ничем не отличаются от любых других сторонних функций, не являющихся явными методами класса.

Довольно полезным нововведением являются "обратные методы-расширения". Эта возможность также следует из того, что нестатические методы первым аргументом принимают неявную ссылку на объект  класса. Иногда возникает необходимость получить "чистую" функцию, не связанную с какими-либо классами и неявными аргументами. Для этого я ввел следующую возможность: любой нестатический метод класса может рассматриваться также как статический с дополнительным аргументом типа "ссылка на объект класса" (или "указатель на объект класса").
class Foo
{
 public def func() {}
};


Foo obj;
obj.func();     // обычный вызов
Foo.func(&obj); // вызов как статического метода

Таким образом, можно получить адрес любого метода класса как обычной функции, и вообще иметь доступ к методам классов как к обычным функциям. Возможность очень простая, и удивительно, что в С++ ее даже не попытались ввести.




No comments:

Post a Comment