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

Материал из Википедии — свободной энциклопедии

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

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

В

.

Реализация в 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].

Примечания

  1. Gardner, 2002, p. 63.
  2. Extension Methods (C# Programming Guide). Дата обращения: 15 февраля 2012. Архивировано 17 февраля 2012 года.
  3. 1 2 Liberty, Xie, 2007.
  4. C# extension methods. Дата обращения: 20 сентября 2014. Архивировано 24 сентября 2014 года.
  5. Bai, 2012.
  6. 1 2 Neal Ford, Are Open Classes Evil? Архивная копия от 4 марта 2016 на Wayback Machine, 2007
  7. Monkeypatching For Humans Архивная копия от 6 сентября 2014 на Wayback Machine, Jeff Atwood, 2008
  8. 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.

Ссылки