Метод расширения
Метод расширения (англ. extension method) в программировании — метод, добавляемый к существующему классу (типу) в месте, отличном от модуля объявления класса. Синтаксический сахар для модуля расширения был введён в C# 3.0 и VB.NET.
Метод расширения не следует путать с относящему к наследованию понятием расширения метода (англ. method extension), существующего в языках CLOS, Smalltalk, Beta, при котором метод суперкласса вызывается до, во время или после вызова метода класса[1].
Реализация в C#
Следующий пример показывает метод расширения, определённый для класса System.String (в языке C# имеет псевдоним string). Заметим, что он определён внутри невложенного и ненастраиваемого статичного класса[2]:
namespace ExtensionMethods
{
public static class MyExtensions
{
// метод WordCount принимает на вход строку, возвращает число слов, т.е. число подстрок, разделённых пробелом, точкой или вопросительным знаком.
public static int WordCount(this string str)
{
return str.Split(new char[] { ' ', '.', '?', '!' },
StringSplitOptions.RemoveEmptyEntries).Length;
}
}
}
/* Метод-расширение WordCount появится в области видимости, если подключить соответствующее пространство имён: */
using ExtensionMethods;
/* Теперь его можно вызвать: */
string s = "Hello Extension Methods";
int i = s.WordCount(); // i получит значение 3
int j = "Съешь же ещё этих мягких французских булок, да выпей чаю.".WordCount(); // j получит значение 10
В сравнении с обычным методом, метод расширения статичен, а первый параметр содержит после this
целевой класс и переменную целевого класса, после чего могут следовать параметры метода[3].
В C# метод расширения имеет доступ только к публичным членам класса. Другим ограничением является то, что если есть и встроенный метод, и расширение, приоритет даётся встроенному методу[3].
Методы расширения широко используются в LINQ. Например, оператор Select является методом расширения интерфейса IEnumerable[4].
Реализация в Visual Basic .NET
В Visual Basic .NET методы расширения позволяют разработчикам добавлять новые возможности типам данных без образования производных типов. Метод расширения может быть только процедурой вида Sub
или Function
, но не свойством, полем или событием. Первый аргумент метода указывает целевой тип данных для расширения. Методы расширения могут определяться только внутри модулей. Как и в C#, метод экземпляра имеет преимущество перед методом расширения, даже если последний обладает более точной сигнатурой[5].
Реализация в Ruby
Язык Ruby имеет аналогичную C# 3.0 возможность, называемую «открытый класс» (англ. open class)[6].
class TestClass
def method1
end
def method2
end
end
test = TestClass.new
test.method1
test.method2
class TestClass
def method3
end
end
test.method3
Кроме того, метод расширения можно добавить не ко всему классу, а только конкретному экземпляру. Более того, в JRuby можно добавить метод к классу из Java[6]. В Ruby, если есть и встроенный метод, и расширение, приоритет дается расширенному методу.
Реализация в других языках
В распространённых динамических языках (JavaScript, Perl, Python, Ruby) механизм метода расширения уже давно может быть реализован (со всеми мерами предосторожности) путём «обезьяньего патча»[7].
В стандарте C++23 методов расширения всё ещё нет, но оставлено место под них — this-параметры[8].
Примечания
- ↑ Gardner, 2002, p. 63.
- ↑ Extension Methods (C# Programming Guide) . Дата обращения: 15 февраля 2012. Архивировано 17 февраля 2012 года.
- ↑ 1 2 Liberty, Xie, 2007.
- ↑ C# extension methods . Дата обращения: 20 сентября 2014. Архивировано 24 сентября 2014 года.
- ↑ Bai, 2012.
- ↑ 1 2 Neal Ford, Are Open Classes Evil? Архивная копия от 4 марта 2016 на Wayback Machine, 2007
- ↑ Monkeypatching For Humans Архивная копия от 6 сентября 2014 на Wayback Machine, Jeff Atwood, 2008
- ↑ Deducing this . Дата обращения: 28 июля 2022. Архивировано 12 июля 2022 года.
Литература
- Liberty, J. and Xie, D. Programming C# 3.0. — O'Reilly Media, 2007. — P. 294-297. — 608 p. — ISBN 9780596554880.
- Papa, J. Data-Driven Services with Silverlight 2. — O'Reilly Media, 2008. — P. 12-14. — 368 p. — ISBN 9780596554422.
- Gardner, T.A. Inheritance Relationships for Disciplined Software Construction. — Springer, 2002. — ISBN 9781852334673.
- Bai, Y. Practical Database Programming with Visual Basic.NET. — Wiley, 2012. — P. 229-232. — 900 p. — ISBN 9781118249826.