Перегрузка методов. Вызов методов с одинаковым именем и разными аргументами

Для того чтобы лучше понять, что такое перегрузка методов необходимо рассмотреть пример вычисления расстояния между двумя точками на плоскости. Предположим, что на плоскости расположены две точки с координатами: Перегрузка методов. Вызов методов с одинаковым именем и разными аргументами - student2.ru и Перегрузка методов. Вызов методов с одинаковым именем и разными аргументами - student2.ru . Воспользовавшись простейшим правилом геометрии расстояние между этими точками будет равно: Перегрузка методов. Вызов методов с одинаковым именем и разными аргументами - student2.ru Ниже представлен код программы.

Предположим, что нам необходимо написать программу вычисляющую значение длинны отрезка с параметрами типа int. Код будет выглядеть следующим образом:

class Plane

{

public double DistanceInt(int x1, int yl, int x2, int y2)

{

return Math.Sqrt(Math.Pow(x1-x2,2) + Math.Pow(y1-y2. 2));

}

}

Список формальных параметров метода DistanceIntсодержит четыре значения типаint(или неявно преобразуемого в него). Однако если потребуется найти расстояние для четырех аргументов типа double , будет необходимо создать другой метод класса Plane, DistanceDouble,который выглядит следующим образом:

class Plane

{

public double DistanceDouble(double x1, double yl, double x2, double y2)

{

return

Math.Sqrt(Math.Pow(x1-x2,2) + Math.Pow(y1-y2. 2));

}

}

Возможен еще и другой случай, когда для представления точек на плоскости используется некий класс Point. Каждый объект этого класса содержит две закрытые переменные экземпляра Перегрузка методов. Вызов методов с одинаковым именем и разными аргументами - student2.ru . Для доступа к ним применяются соответствующие методы (асессор и мутатор).

class Point

{

private int x = 0;

private int y = 0;

public void setX(int newX)

{

x = newX;

}

public void setY(int newY)

{

y=newY;

}

public int getX()

{

return x;

}

public int getY()

{

return y;

}

}

Теперь для расчета расстояния (с помощью методов созданных ранее) удобнее указать четыре числовых аргумента и два объекта :

public double DistanceObjects(location L1, location L2)

return

Math.Sqrt(Math.Pow(L1.getX()-L2.getX(),2)+Math.Pow(L1.getY() - L2.getY(),2));

}

Из написанных кодов можно сделать следующий вывод, что три метода с разными именами, по существу, решают одну задачу — вычисля­ют расстояние. Разумеется, было бы проще и естественнее (независимо от типа аргу­ментов — int, double или Location) использовать одно имя Distance.

При этом компилятор автоматически выбирает правильный путь для обработки ар­гументов. Такой подход возможен благодаря перегрузке метода.

Эта концепция позво­ляет определять в одном классе несколько различных методов с одним именем, но раз­ными наборами формальных параметров и реализацией. Для перегрузки метода в данном случае (чтобы три приведенных вызова были корректными вместе с возвращаемыми ими значениями) достаточно просто присвоить всем трем методам одно имя — Distance. Тело каждого из них останется без изменений, а заголовки будут выглядеть так:

public double Distance(int x1, int y1, int х2, int y2)

public double Distance{double x1, double yl. double x2, double y2)

public double Distance(Location LI, Location L2)

Теперь, когда компилятор встречает оператор Plane.Distance(10, 10, 20, 30), он совершает следующие действия. Вначале в классе Plane производится поиск метода с именем Distance.Компилятор находит три таких метода. Он выбирает тот из них, чей набор формальных параметров совпадает с аргументами в вызове. Такое со­впадение требует, чтобы:

1 Число аргументов в вызове было равно числу формальных параметров.

2 Каждый аргумент имеет тип, совместимый с типом соответствующего ему фор­мального параметра.

Следуя этой процедуре, компилятор выбирает метод Distance с заголовком:

public double Distance(int x1, int у1, int х2, int y2)

Приведем код программы, которая реализует данный подход:

using System;

class DistanceCalculator

{

public static void Main()

{

Plane myPlane = new Plane();

Point location1 = new Point();

Point location2 = new Point();

location1.setX(10);

location1.setY(10);

location2.setX(10);

location2.setY(20);

Console.WriteLine("integers: " + myPlane.Distance(5,10,5,30));

Console.WriteLine("doubles: " + myPlane.Distance(15.4, 20.6, 15.4, 30.60));

Console.WriteLine("objects:" + myPlane.Distance(location1, location2));

}

}

class Plane

{

public double Distance (int x1, int y1, int x2, int y2)

{

Console. WriteLine("\nUsing the integer version");

return Math.Sqrt( Math.Pow(x1-x2,2) + Math.Pow(y1-y2,2));

}

public double Distance (double x1, double y1, double x2, double y2)

{

Console.WriteLine("\nUsing the double version");

return Math.Sqrt( Math.Pow(x1-x2, 2) + Math.Pow(y1-y2, 2));

}

public double Distance ( Point L1, Point L2)

{

Console.WriteLine("\nUsing the Location objects version");

return Math.Sqrt(Math.Pow(L1.getX()-L2.getX(),2)+Math.Pow(L1.getY() - L2.getY(),2));

}

}

class Point

{

private int x = 0;

private int y = 0;

public void setX(int newX)

{

x = newX;

}

public void setY(int newY)

{

y=newY;

}

public int getX()

{

return x;

}

public int getY()

{

return y;

}

}

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

С перегрузкой метода связана важная концепция — сигнатура метода. Имя метода вместе с числовым типом и порядком формальных параметров составля­ют сигнатуру метода.

Однако стоит отметить следующие исключения.

Возвращаемое значение не включено в сигнатуру метода. Таким образом, следу­ющие три заголовка имеют одинаковую сигнатуру (несмотря на то, что первый возвращает значение double,второй int, а третий не возвращает значения):

public double Sum (double a, double b)

public int Sum (double a, double b)

public void Sum (double a, double b)

Ключевое слово paramsвсигнатуре метода игнорируется. Следовательно, следу­ющие два заголовка имеют одинаковую сигнатуру:

public double Sum (params double[] numbers)

public double Sum (double[] numbers)

Имена формальных параметров не включаются в сигнатуру метода. Сигнатуры двух следующих методов совпадают:

public int Sum (double x, double y)

public int Sum (double a, double b)

Все методы в классе должны иметь разные сигнатуры. Поскольку имя метода — один из нескольких атрибутов, определяющих сигнатуру метода, в одном классе можно оп­ределить несколько методов с одним именем при условии, что остальные элементы сиг­натур различаются. Такие методы называются перегруженными,

Перегруженные методы широко используются в классах .NET.

Рассмотрим, как согласуется перегрузка методов и неявное преобразование.

Конструкторы экземпляра

Конструктор экземпляра класса представляет собой специальный метод, запускаемый по ключевому слову new. Он используется для инициализации переменных и других операций при создании объекта.

Определение конструктора экземпляра представлено в следующем синтаксическом блоке

Определение_конструктора_экэемпляра::=

[<Спецификатор_конструктора>] <Идентификатор__конструктора> ([<Список_формальных_параматров> ] )

[<Инициализатор_конструктора> ]

<Тело_конструктора>

где:

<Спецификатор_конструктора>

::= private

;:= public

::= protected

::= internal

<Инициализатор_конструктора>

::= : base ( [<Список_аргументов>] )

::= : this ( [<Список_аргументов>] )

{

<Операторы>

}

Стоит отметить, что Идентификатор_конструктора должен быть таким же, как идентификатор его класса. Скажем, конструктор класса Carтакже должен называться Car. Конструктор экземпляра не возвращает значения, поэтому тип возвращаемого зна­чения не указывается (не используется даже ключевое слово void).<Инициализатор_конструктора> вызывает исполнение другого конструктора экзем­пляра до того как исполнить операторы исходного.

Чтобы включить конструктор в класс, необходимо разместить его внутри блока опреде­ления класса вместе с другими элементами.

С конструктором экземпляра может применяться необязательный спецификатор доступности privateили public.Он управляет доступностью конструктора так же, как переменных и методов экземпляра, однако имеются и различия

Аналогично тому как в заголовке обычного метода, в объявлении конструктора экземпляра используются круглые скобки, включающие список формальных параметров. Значения аргументов передаются этим параметрам во время создания объекта с помощью ключевого слова new.

Подобно своим методам, конструктор экземпляра может быть перегружен путем объявления нескольких конструкторов одного класса с разными списками фор­мальных параметров.

Если класс содержит несколько конструкторов экземпляра (которые, таким образом, являются перегруженными), можно дополнительно указать конструктор того же клас­са, который будет исполняться перед операторами объявленного конструктора. Для этого после списка формальных параметров размешается инициализатор конструктора: this ( [<Список_аргументов>] ). Среда исполнения запускает тот конструктор экземпляра класса, список формальных параметров которого совпадает со списком аргументов ини­циализатора.

Конструктор экземпляра содержит тело, подобное телу метода. Это означает, что оно может состоять из пустого оператора (точка с запятой) или группы операторов, заклю­ченных в пару фигурных скобок. При вызове конструктора операторы исполняются в той же последовательности, как и при вызове метода. Однако они должны содержать только команды, непосредственно связанные с инициализацией и созданием объекта.

Наши рекомендации