Принцип полиморфизма реализуется, в том числе, через использование абстрактных классов, методов и свойств. Дадим определения и рассмотрим пример.
Абстрактный класс
Абстрактный класс объявляется с ключевым словом abstract. Такой класс имеет свои правила:
1) нельзя создавать экземпляры (объекты) абстрактного класса;
2) абстрактный класс может содержать как абстрактные методы/свойства, так и обычные;
3) в классе-наследнике должны быть реализованы все абстрактные методы и свойства, объявленные в базовом классе.
Заметим, что в абстрактном классе, от которого ничего не наследуется, смысла нет, так как нельзя создавать его экземпляры. В абстрактном классе обычно реализуется некоторая общая абстрактная сущность, которая, как объект, не может существовать, но эта часть необходима в классах-наследниках.
В отличие от языка C++, в C# множественное наследование не допускается. Однако добавить функциональность в классы-наследники можно через механизм интерфейсов.
Абстрактные методы
Абстрактный метод – это метод, который не имеет своей реализации в базовом классе, но он должен быть реализован в классе-наследнике. Абстрактный метод может быть объявлен только в абстрактном классе.
Объявление абстрактного метода происходит при помощи ключевого слова abstract, и при этом фигурные скобки опускаются, точка с запятой ставится после заголовка метода:
[модификатор доступа] abstract [тип] [имя метода] ([аргументы]);
Реализация абстрактного метода в классе-наследнике происходит так же, как и переопределение метода, при помощи ключевого слова override:
[модификатор доступа] override [тип] [имя метода] ([аргументы])
{
// реализация метода
}
Абстрактные свойства
Создание абстрактных свойств не сильно отличается от методов:
protected [тип] [поле, которым управляет свойство];
[модификатор доступа] abstract [тип] [имя свойства] { get; set; }
Реализация в классе-наследнике:
[модификатор доступа] override [тип] [имя свойства]
{
get { тело аксессора get }
set { тело аксессора set }
}
Пример «Правильный многоугольник»
Создадим абстрактный класс Figure, определяющий правильный многоугольник.
abstract class Figure { public double Length { get; set; } protected double Area; protected double Perimeter; public Figure(double len) { this.Length = len; Area=area(); Perimeter=perimeter(); } public void InfoFigure(string s) { Console.WriteLine(s + ": площадь = {0:###.###}, периметр = {1:###.###}", Area, Perimeter); } public abstract double area(); public abstract double perimeter(); }
где Length, Area, Perimeter – длина стороны, площадь и периметр многоугольника;
Figure( ) и InfoFigure( )– конструктор класса и обычный (не абстрактный) метод класса;
area( ) и perimeter( ) – абстрактные методы класса, в конструкторе они используются для нахождения полей класса Area и Perimeter.
Наследуем от абстрактного класса Figure класс Square («Квадрат»):
class Square : Figure { public Square(double len) : base(len) { } public override double area() { Area = Length * Length; return Area; } public override double perimeter() { Perimeter = 4 * Length; return Perimeter; } }
В этом классе производится перегрузка конструктора Square( ), наследуемого от конструктора базового (base) класса Figure( ) – дополнительно вызываются методы area( ) и perimeter( ), которые конкретизируются далее.
Аналогично наследуем от абстрактного класса Figure класс Triangle («Треугольник»):
class Triangle : Figure { public Triangle(double len) : base(len) { } public override double area() { Area = Length * Length * Math.Sqrt(3) / 4; return Area; } public override double perimeter() { Perimeter = 3 * Length; return Perimeter; } }
и класс Circle («Окружность» — задается диаметр):
class Circle : Figure { public Circle(double len) : base(len) { } public override double area() { Area = Math.PI*Length*Length; return Area; } public override double perimeter() { Perimeter = 2 * Math.PI * Length; return Perimeter; } }
Как мы видим, добавление нового n-угольника сводится к объявлению класса-наследника и определению абстрактных методов определения площади и периметра многоугольника.
В классе Program( ) создадим соответствующие объекты и вызовем методы классов-наследников:
class Program { static void Main(string[] args) { Console.Write("Характерный размер фигуры = "); double len = Convert.ToDouble(Console.ReadLine()); Console.WriteLine(); Circle c = new Circle(len); c.InfoFigure("Круг (радиус)"); Console.WriteLine(" площадь = {0:###.###}", c.area()); Square q = new Square(len); q.InfoFigure("Квадрат"); Console.WriteLine("сторона квадрата = {0:###.###}", q.Length); Triangle t = new Triangle(len); t.InfoFigure("Треугольник"); Console.WriteLine("периметр = {0:###.###}", t.perimeter()); Console.ReadKey(); } }
Результат:
Для тренировки добавьте класс Hexagon («Шестиугольник»), сравните полученные результаты с кругом.
Другая реализация принципа полиморфизма предполагает использование интерфейсов.
NEW: Наш Чат, в котором вы можете обсудить любые вопросы, идеи, поделиться опытом или связаться с администраторами.