Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции ЛИПО .doc
Скачиваний:
0
Добавлен:
06.12.2018
Размер:
441.86 Кб
Скачать

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

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

Предположим, что нам необходимо написать программу вычисляющую значение длинны отрезка с параметрами типа 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. Каждый объект этого класса содержит две закрытые переменные экземпляра . Для доступа к ним применяются соответствующие методы (асессор и мутатор).

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.

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