|
Введение в классы - Наследование (часть 8)
НАСЛЕДОВАНИЕ
Чтобы построить (в терминах данных или поведения) класс на основе другого класса, применяется наследование. Оно принадлежит к правилам заменяемости, а именно к тому, которое гласит, что производный класс может быть заменен базовым. Примером этого может служить написание иерархии классов базы данных. Допустим, вам был нужен класс для обработки баз данных Microsoft SQL Server и Oracle. Поскольку эти базы различны, вам понадобится по классу для каждой из БД. Однако в обеих БД достаточная доля общей функциональности, которую можно поместить в базовый класс, а два других класса сделать его производными, при необходимости подменяя или изменяя поведение, унаследованное от базового класса.
Чтобы унаследовать один класс от другого, используется синтаксис:
class <производный_класс>: <базовый_класс>
Вот пример того, на что может быть похожа такая программа с базами данных:
using System;
class Database
{
public Database()
{
CommonField = 42;
}
public int CommonField;
public void CommonMethod()
{
Console.WriteLine("Database.Common Method");
}
class SQLServer : Database
{
public void SomeMethodSpecificToSQLServer()
{
Console.WriteLine("SQLServer.SomeMethodSpecificToSQLServer");
}
}
class Oracle : Database
{
public void SomeMethodSpecificToQracle()
{
Console.WriteLine("Oracle.SomeMethodSpecificToOracle");
}
class InheritanceApp
{
public static void Main()
{
SQLServer sqlserver = new SQLServer();
sqlserver.SomeMethodSpecificToSQLServer();
sqlserver.CommonMethod();
Console.WriteLine("Inherited common field = {0 } ", sqlserver.CommonField);
}
}
}
}
|
Заметьте: методы Data base. Common Method и Database.CommonField теперь являются частью определения класса SQLServer. Так как классы SQLServer и Oracle происходят от базового класса Database, оба наследуют практически все его члены, определенные как public, protected или internal. Единственное исключение — конструктор, который не может быть унаследован. У каждого класса должен быть реализован собственный конструктор, независимый от базового класса.
Cледует заметить, что подмена методов позволяет изменять реализацию унаследованных от базового класса методов. Абстрактные классы интенсивно используют подмену методов (см. ниже).
Для наглядности давайте рассмотрим еще один пример. Представьте, что у нас есть некоторый класс (быть может, весьма большой), который почти подходит для нашей конкретной задачи. Почти, но не совсем. Чтото (некоторые методы) в этом классе надо изменить, что-то — добавить.
Наследование как раз и служит для этого. При наследовании мы объявляем наш класс потомком другого класса. И наш класс-потомок (или, как его еще называют, дочерний класс) автоматически приобретает все, что было в родительском классе. Это мы делаем буквально парой строчек.
Затем в дочерний класс мы можем что-нибудь добавить (чего не было в классе родительском). Кроме того, в дочернем классе мы можем что нибудь из родительского класса переопределить — так, что оно уже будет работать по-другому.
Например, у нас будет класс Worker и производный от него класс Boss.
Класс Boss будет отличаться от класса Worker, во-первых, наличием переменной numOfWorkers (для количества подчиненных) и, во-вторых, другой работой в Boss метода для задания возраста (setAge):
using System;
namespace test
{
//Класс Worker
class Worker
{
protected int age = 0;
public void setAge(int age)
{
if (age > 0 && age < 100)
this.age = age;
else
this.age = 0;
}
public int getAge()
{
return age;
}
//Класс Boss
class Boss : Worker
{
public int numOfWorkers; //Количество подчиненных
public new void setAge(int age)
{
if (age > 0 && age < 45)
this.age = age;
else
this.age = 0;
}
}
class Test
{
static void Main(string[] args)
{
Worker wrkl = new Worker();
Boss boss = new Boss();
wrkl.setAge(50);
boss.setAge(50);
boss.numOfWorkers = 4;
Console.WriteLine("Возраст работника " + wrkl.getAge());
Console.WriteLine("Возраст босса " + boss.getAge() + " \nКоличество подчиненных " + boss.numOfWorkers);
}
}
}
}
|
Обратите внимание, как мы вводим новый класс Boss:
class Boss: Worker{
Такая запись и означает, что новый класс Boss будет потомком другого класса (Worker в данном случае) и, следовательно, будет автоматически уметь все то же самое, что и родительский класс. В частности, в нем есть переменная age для хранения возраста. Далее, в класс Boss мы вводим переменную numOfWorkers для хранения количества подчиненных у нашего босса. В родительском классе такой переменной не было.
Кроме того, нас не устроила реализация метода setAge из родительского класса Worker (по каким-то внутренним инструкциям фирмы возраст босса не может превышать 45 лет, тогда как возраст работника не может превышать 100), поэтому мы просто написали в классе Boss метод с таким же именем. Обратите внимание на слово new при объявлении метода:
public new void setAge(int age)
Таким образом, в производном классе мы можем что-нибудь добавлять и что-нибудь изменять по отношению к классу родительскому. При этом убирать что-нибудь полученное в наследство от родительского класса мы не можем.
После запуска наша программа выдаст вполне ожидаемый результат:
Возраст работника 50
Возраст босса 0
Количество подчиненных 4
Предыдущая стр.   
Оглавление   
Следующая стр.
Средняя оценка:     (3,5 - 2 голосов) Для оценки необходимо зарегистрироваться
Только зарегистрировавшиеся пользователи могут оставлять комментарии
|
|