Метод расширения


Метод расширения (англ. extension method) в программировании — метод, добавляемый к существующему классу (типу) в месте, отличном от модуля объявления класса. Синтаксический сахар для модуля расширения был введён в C# 3.0 и VB.NET.

Метод расширения не следует путать с относящему к наследованию понятием расширения метода (англ. method extension), существующего в языках CLOS, Smalltalk, Beta, при котором метод суперкласса вызывается до, во время или после вызова метода класса.

Реализация в C#

Следующий пример показывает метод расширения, определённый для класса System.String (в языке C# имеет псевдоним string). Заметим, что он определён внутри невложенного и ненастраиваемого статичного класса:

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 целевой класс и переменную целевого класса, после чего могут следовать параметры метода.

В C# метод расширения имеет доступ только к публичным членам класса. Другим ограничением является то, что если есть и встроенный метод, и расширение, приоритет даётся встроенному методу.

Методы расширения широко используются в LINQ. Например, оператор Select является методом расширения интерфейса IEnumerable.

Реализация в Visual Basic .NET

В Visual Basic .NET методы расширения позволяют разработчикам добавлять новые возможности типам данных без образования производных типов. Метод расширения может быть только процедурой вида Sub или Function, но не свойством, полем или событием. Первый аргумент метода указывает целевой тип данных для расширения. Методы расширения могут определяться только внутри модулей. Как и в C#, метод экземпляра имеет преимущество перед методом расширения, даже если последний обладает более точной сигнатурой.

Реализация в Ruby

Язык Ruby имеет аналогичную C# 3.0 возможность, называемую «открытый класс» (англ. open class).

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. В Ruby, если есть и встроенный метод, и расширение, приоритет дается расширенному методу.

Реализация в других языках

В распространённых динамических языках (JavaScript, Perl, Python, Ruby) механизм метода расширения уже давно может быть реализован (со всеми мерами предосторожности) путём «обезьяньего патча».

В C++ механизм методов расширения находится на этапе рассмотрения комитетом по стандартизации языка .