Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Questions

.pdf
Скачиваний:
9
Добавлен:
11.03.2016
Размер:
1.14 Mб
Скачать

Теперь вопросы:

1. Измените этот пример и закомментируйте метод Speak(Cat c).

-Скомпилируйте и запустите программу.

-Проанализируйте результаты работы программы. Что происходит, когда Вы вызываете метод

Speak, передавая ему в качестве параметра объект типа Cat. - поделитесь Вашими наблюдениями в форуме.

Происходит следующее.

Мы имеем несколько перегруженных методов Speak ( ); Различия в сигнатуре – разные типы аргументов и их имена. И при вызове метода Speak вызывается та его версия, тип параметра которого наиболее полно соответствует типу передаваемого аргумента. Автоматическое

преобразование применяется только в том случае, когда не существует прямого соответствия параметра и аргумента. Вот и в таком случае, при отсутствии подходящего метода Speak (Cat c)

вызывается метод Speak(object o) как самый подходящий при автоматическом преобразовании типа аргумента в тип параметра. Так как все типы унаследованы от типа object, то нет никаких проблем при преобразовании какого-либо типа в тип object.

2. Дан следующий код:

using System;

class Dog : Animal

{

public string s;

}

class Cat : Animal

{

public string s;

}

//An example to demonstrate method overloading (and not the best example regarding

//object oriented programming!)

class OverloadExample

{

static void Main()

{

Dog dog = new Dog(); dog.s = "I'm a dog";

Cat cat = new Cat(); cat.s = "I'm a cat";

Speak(dog);

Speak(cat);

Speak((object) dog); // Explicit cast to force the right overloaded method to be called

}

//Speak is overloaded three times: one method expects a Dog as it's argument, the second

//expects a Cat as it's argument and the third expects an object as it's argument.

static void Speak(Dog d)

{

Console.WriteLine("A dog barks");

}

static void Speak(Animal a)

{

Console.WriteLine("Most animals can make noise.");

}

}

-Создайте новый класс Animal.

-Сделайте так, чтобы классы Cat и Dog наследовались от класса Animal

-Создайте метод Speak(Animal a), который печатает строку " Most animals can make noise."

Скомпилируйте и запустите программу

Пример:

using System;

class Animal

{

public string s;

}

class Dog : Animal

{

public string s;

}

class Cat : Animal

{

public string s;

}

//An example to demonstrate method overloading (and not the best example regarding

//object oriented programming!)

class OverloadExample

{

static void Main()

{

Dog dog = new Dog(); dog.s = "I'm a dog";

Cat cat = new Cat(); cat.s = "I'm a cat";

Animal animal = new Animal(); // Сoздаем объект класса Animal animal.s = "I'm an animal"; // Инициализируем переменную s

Speak(dog);

 

Speak(cat);

// Вызываем перегруженный метод Speak для типа

Speak(animal);

параметра (аргумента) Animal

// Explicit cast to force the right overloaded method to

Speak((object)dog);

be called

 

Console.Read();

 

}

 

//Speak is overloaded three times: one method expects a Dog as it's argument, the

second

//expects a Cat as it's argument and the third expects an object as it's argument.

static void Speak(Dog d)

{

Console.WriteLine("A dog barks");

}

static void Speak(Animal a) // Метод для типа Animal

{

Console.WriteLine("Most animals can make noise.");

}

}

-Посмотрите, что она выводит и объясните то, что Вы видите.

Компилятор не может конвертировать тип object в dog.

-Что происходит, когда вы вызываете метод Speak, передавая ему в качестве параметра объект типа Cat?

При вызове метода Speak с передачей ему в параметр объект Cat происходит поиск

подходящей версии метода Speak, а именно Speak (Cat m); Если такового нет, то ищется более подходящий – такой, который позволяет автоматически преобразовать в определенный и возможный для конвертации тип. Так как классы Dog и Cat наследуются от класса Animal, то при вызове метода Speak(cat) в работу включается версия

static void Speak(Animal a) // Метод для типа Animal

{

Console.WriteLine("Most animals can make noise.");

}

как самая подходящая для конвертации типов.

3.Обсудите в форуме чем полезна и вредна перегрузка методов. Какие возможности она предоставляет, чего следует избегать при использовании перегрузки методов? Приведите Ваши

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

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

(версии метода) происходит преобразование типов аргумента в типы параметров.

Недостаток тот, что C# не поддерживает необязательные параметры и потому для достижения такого эффекта необходимо использовать перегруженные методы:

class som

{

int function(int i) // а необходимо два параметра и второй должен иметь значение

100

{

function2(i, 100);

}

int function2(int i, int j)

{

//что-то выполняем

}

}

Пример полезных перегрузок:

using System;

class myclass

{

static int i = 1;

static int[] m = new int[] { 1, 2, 3, 4, 5}; static bool b = true;

static string s = "Only string";

public static void Main()

{

Send(i);

Send(m);

Send(b);

Send(s);

}

public static void Send(int x)

{

Console.WriteLine(x);

Console.ReadLine();

}

public static void Send(int[] x)

{

for (int i = 0; i < x.Length;)

{

Console.WriteLine(" m [" + i + "] = " + x[i]); i++;

}

Console.ReadLine();

}

public static void Send(bool x)

{

Console.WriteLine(x);

Console.ReadLine();

}

public static void Send(string x)

{

Console.WriteLine(x);

Console.ReadLine();

}

}

Здесь для каждого типа аргумента вызывается соответствующая типу аргумента версия

метода Send ( ), который определенным образом обрабатывает параметр.

Еще пример:

using System;

static class Ticket

{

static int count = 1;

public static void Main()

{

string name = "Nesterovskij"; string type = "luxe";

int number = 1917;

rezume( name, type, number); name = "Shtolz";

number = 1915; rezume(name, number); name = "Polina"; number = 1937; rezume(name); Console.Read();

}

static void rezume(string name, string type, int number)

{

Console.WriteLine(count + ".| Hello, " + name + ". You have a " + type + " room, and it's number is " + number + ".");

count++; Console.ReadLine();

}

static void rezume(string name, int number)

{

Console.WriteLine(count + ".| Hello, " + name +

". You have a common room, and it's number is " + number + ".");

Console.ReadLine(); count++;

}

static void rezume(string name)

{

Console.WriteLine(count + ".| Hello, " + name + ". You did not yet book room!");

Console.Read();

}

}

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

Теперь, когда Вы разобрались с перегрузкой методов, можно перейти к перегрузке операторов.

Перегружены могут быть не все, а только следующие операторы:

Унарные операторы: +, -, !, ~, ++, --, true, false

Бинарные операторы: +, -, *, / , %, &, |, ^, <<, >>, ==, !=, >, <, >=, <=

Наиболее часто перегружают операторы + и -, а также операторы сравнения.

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

Изучите следующий пример:

using System;

class Point

{

//Constructor to initialize a new point public Point(int x, int y)

{

this.x = x; this.y = y;

}

//Equality operator to determine if two points have the same value

//If we override operator==, we should also override Equals() and GetHashCode() public static bool operator== (Point p1, Point p2)

{

if (p1.x == p2.x && p1.y == p2.y)

return true; return false;

}

//Equality operator to determine if two points have different values

//If we override operator!=, we should also override Equals() and GetHashCode() public static bool operator!= (Point p1, Point p2)

{

if (p1.x != p2.x || p1.y != p2.y) return true;

return false;

}

public int x; public int y;

}

class OverloadedPointExample

{

static void Main()

{

string sx; string sy;

// Read values for p1.x and p1.y from the console Console.Write("Enter a value for p1.x: ");

sx = Console.ReadLine();

Console.Write("Enter a value for p1.y: "); sy = Console.ReadLine();

//Create a new Point using the values we got from the user Point p1 = new Point(Convert.ToInt32(sx), Convert.ToInt32(sy));

//Read values for p2.x and p2.y from the console Console.Write("Enter a value for p2.x: ");

sx = Console.ReadLine();

Console.Write("Enter a value for p2.y: "); sy = Console.ReadLine();

//Create a new Point using the values we got from the user Point p2 = new Point(Convert.ToInt32(sx), Convert.ToInt32(sy));

//Use the overloaded operator== to compare p1 and p2

if (p1 == p2)

Console.WriteLine("p1 == p2, the points are the same.");

else

Console.WriteLine("p1 != p2, the points are different.");

}

}

Этот пример реализует класс Point, который содержит два поля – x и y, а так же перегруженные операторы == и !=. Давайте рассмотрим эти два оператора и разберемся, что здесь происходит.

Операторы сравнения == и != определяют, одинаковы ли значения полей x и y у двух объектов класса Point. Обратите внимание на оператор !=

public static bool operator!= (Point p1, Point p2)

{

if (p1.x != p2.x || p1.y != p2.y)

{

return true;

}

return false;

}

Если поля x и y двух объектов содержат разные значения, то оператор возвращает true, если же эти поля равны, то он возвращает false.

Внимание, теперь вопросы к обсуждению.

1.Дополните пример таким образом, чтобы можно было складывать и вычитать две точки

(покомпоненно, как векторы). Например, если поле p1.x было равно 5, а поле p2.x было равно

7, то поле x в объекте-сумме должно быть равно 12. Аналогично для y.

Пример:

using System;

class Point

{

// Constructor to initialize a new point

//Possible to initialize a new point by zero automatically /*public Point()

//{

//x=y=0;

}*/

public Point(int x, int y)

{

this.x = x; this.y = y;

}

//image of our results public void show()

{

Console.WriteLine("x = " + x + ", y = " + y); Console.ReadLine();

}

//Equality operator to determine if two points have the same value

//If we override operator==, we should also override Equals() and GetHashCode() public static bool operator== (Point p1, Point p2)

{

if (p1.x == p2.x && p1.y == p2.y)

return true; return false;

}

//Equality operator to determine if two points have different values

//If we override operator!=, we should also override Equals() and GetHashCode() public static bool operator!= (Point p1, Point p2)

{

if (p1.x != p2.x || p1.y != p2.y)

return true; return false;

}

//Override + operator

public static Point operator+ (Point pp1, Point pp2)

{

Point sum = new Point(0,0); sum.x = pp1.x + pp2.x; sum.y = pp1.y + pp2.y;

return sum;

}

//Override - operator

public static Point operator -(Point pp1, Point pp2)

{

Point sum = new Point(0, 0); sum.x = pp1.x - pp2.x; sum.y = pp1.y - pp2.y; return sum;

}

public int x; public int y;

}

class OverloadedPointExample

{

static void Main()

{

string sx; string sy;

// Read values for p1.x and p1.y from the console Console.Write("Enter a value for p1.x: ");

sx = Console.ReadLine();

Console.Write("Enter a value for p1.y: "); sy = Console.ReadLine();

//Create a new Point using the values we got from the user Point p1 = new Point(Convert.ToInt32(sx), Convert.ToInt32(sy));

//Read values for p2.x and p2.y from the console

Console.Write("Enter a value for p2.x: "); sx = Console.ReadLine();

Console.Write("Enter a value for p2.y: "); sy = Console.ReadLine();

//Create a new Point using the values we got from the user Point p2 = new Point(Convert.ToInt32(sx), Convert.ToInt32(sy));

//Use the overloaded operator== to compare p1 and p2

if (p1 == p2)

Console.WriteLine("p1 == p2, the points are the same.");

else

Console.WriteLine("p1 != p2, the points are different."); Console.ReadLine();

//Create with following image a new point result of using overridig operators Point p3 = new Point(0,0);

p3 = p1+p2;

Console.WriteLine("Результат скложения двух векторов:"); p3.show();

p3 = p1 - p2;

Console.WriteLine("Результат вычитания двух векторов:"); p3.show();

}

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]