| Инкапсуляция |
Наследование классов
Класс object
Корневой класс System.Object всей иерархии объектов .NET, называемый в C# object, обеспечивает всех наследников несколькими важными методами. Производные классы могут использовать эти методы непосредственно или переопределять их.
Класс object часто используется и непосредственно при описании типа параметров методов для придания им общности, а также для хранения ссылок на объекты различного типа — таким образом реализуется полиморфизм.
Открытые методы класса System.Object перечислены ниже.
- Метод Equals с одним параметром возвращает значение true, если параметр и вызывающий объект ссылаются на одну и ту же область памяти. Синтаксис:
public virtual bool Equals(object obj);
- Метод Equals с двумя параметрами возвращает значение true, если оба параметра ссылаются на одну и ту же область памяти. Синтаксис:
public static bool Equals(object ob1, object ob2);
- Метод GetHashCode формирует хэш-код объекта и возвращает число, однозначно идентифицирующее объект. Это число используется в различных структурах и алгоритмах библиотеки. Если переопределяется метод Equals, необходимо перегрузить и метод GetHashCode. Синтаксис:
public virtual int GetHashCode();
- Метод GetType возвращает текущий полиморфный тип объекта, то есть не тип ссылки, а тип объекта, на который она в данный момент указывает. Возвращаемое значение имеет тип Type. Это абстрактный базовый класс иерархии, использующийся для получения информации о типах во время выполнения. Синтаксис:
public Type GetType();
- Метод ReferenceEquals возвращает значение true, если оба параметра ссылаются на одну и ту же область памяти. Синтаксис:
public static bool ReferenceEquals(object ob1, object ob2);
- Метод ToString по умолчанию возвращает для ссылочных типов полное имя класса в виде строки, а для значимых — значение величины, преобразованное в строку. Этот метод переопределяют для того, чтобы можно было выводить информацию о состоянии объекта. Синтаксис:
public virtual string ToString()
В производных объектах эти методы часто переопределяют. Например, можно переопределить метод Equals для того, чтобы задать собственные критерии сравнения объектов.
Пример применения и переопределения методов класса object для класса Monster приведен в листинге 8.5.
using System;
namespace ConsoleApplication1
{
class Monster
{
public Monster( int health, int ammo, string name )
{
this.health = health;
this.ammo = ammo;
this.name = name;
}
public override bool Equals( object obj )
{
if ( obj == null || GetType() != obj.GetType() ) return false;
Monster temp = (Monster) obj;
return health == temp.health &&
ammo == temp.ammo &&
name == temp.name;
}
public override int GetHashCode()
{
return name.GetHashCode();
}
public override string ToString()
{
return string.Format( "Monster {0} \t health = {1} ammo = {2}",
name, health, ammo );
}
string name;
int health, ammo;
}
class Class1
{ static void Main()
{
Monster X = new Monster( 80, 80, "Вася" );
Monster Y = new Monster( 80, 80, "Вася" );
Monster Z = X;
if ( X == Y ) Console.WriteLine(" X == Y ");
else Console.WriteLine(" X != Y ");
if ( X == Z ) Console.WriteLine(" X == Z ");
else Console.WriteLine(" X != Z ");
if ( X.Equals(Y) ) Console.WriteLine( " X Equals Y " );
else Console.WriteLine( " X not Equals Y " );
Console.WriteLine(X.GetType());
}
}
}
Листинг
8.5.
Перегрузка методов класса object
Результат работы программы:
X != Y X == Z X Equals Y ConsoleApplication1.Monster
Анализируя результат работы программы, можно увидеть, что в операции сравнения на равенство сравниваются ссылки, а в перегруженном методе Equals — значения. Для концептуального единства можно переопределить и операции отношения.
Вопросы и задания для самостоятельной работы студента
- Для чего используется наследование?
- Опишите синтаксис производного класса. Какие спецификаторы доступа применяются в иерархиях?
- Как вызвать метод базового класса из производного?
- Опишите порядок вызова конструкторов базовых классов при работе конструктора производного класса.
- Какие ключевые слова используется при переопределении методов базового класса в производном?
- Опишите механизмы раннего и позднего связывания.
- Опишите процесс вызова виртуального метода. Для чего применяются виртуальные методы?
- Все ли методы следует описывать как виртуальные?
- Для чего используются абстрактные классы?
- Какие методы и операции класса object часто перегружают в его потомках?
- Назовите альтернативы наследованию классов.
- Изучите по справочной системе свойства и методы класса object.
- Изучите разделы стандарта C#, касающиеся наследования.
Лабораторная работа 9. Наследование
В программах требуется описать базовый класс (возможно, абстрактный), в котором с помощью виртуальных или абстрактных методов и свойств задается интерфейс для производных классов. Целью лабораторной работы является максимальное использование наследования, даже если для конкретной задачи оно не дает выигрыша в объеме программы. Во всех классах следует переопределить метод Equals, чтобы обеспечить сравнение значений, а не ссылок.
Функция Main должна содержать массив из элементов базового класса, заполненный ссылками на производные классы. В этой функции должно демонстрироваться использование всех разработанных элементов классов.
Задание
Создать абстрактный класс Pair (пара значений) с виртуальными арифметическими операциями и методом вывода на экран. На его основе реализовать классы Money (деньги) и Complex (комплексное число).
В классе Money денежная сумма представляется в виде двух целых, в которых хранятся рубли и копейки соответственно. При выводе части числа снабжаются словами "руб." и "коп.". В классе Complex предусмотреть при выводе символ мнимой части (i).
Создать класс Series (набор), содержащий список (или массив) объектов этих классов в динамической памяти. Предусмотреть возможность вывода объектов списка. Написать демонстрационную программу, в которой будут использоваться все методы классов.