Абстрактные классы и методы
Абстрактные методы – это методы у которых отсутствует реализация.
аbstract тип имяМетода(списокПараметоров);
public abstract double calculateArea();
Абстрактные методы должны быть обязательно переопределены в подклассе.
Любой класс, содержащий один или больше абстрактных методов, должен быть также объявлен как абстрактный. Для этого достаточно указать ключевое слово abstract перед ключевым словом class в начале объявления класса:
public abstract class Figure2
У абстрактного класса в Java не может быть никаких объектов. Но абстрактные классы можно применять для создания ссылок на объекты. Например:
public abstract class Figure2 < . public abstract double calculateArea(); public static void main(String[] args) < // У абстрактного класса не может быть никаких объектов. // Figure2 figure1 = new Figure2(); // Но абстрактные классы можно применять для создания ссылок на объекты. Figure2 figure2 = new Rectangle(); >>
Также нельзя объявлять абстрактные конструкторы или абстрактные статические методы.
Рассмотрим пример использования абстрактных классов и методов на примере класса Figure и его наследников Triangle и Rectangle , которые мы рассматривали в Переопределение методов. Класс Figure описывает абстрактную фигуру, для которой вычисление площади не имеет смысла, поэтому метод calculateArea() более правильно сделать абстрактным.
public abstract class Figure2 < double dimension1; double dimension2; public Figure2(double dimension1, double dimension2) < this.dimension1 = dimension1; this.dimension2 = dimension2; >public abstract double calculateArea(); >
Любой подкласс, производный от абстрактного класса, должен реализовать все абстрактные методы из своего супер класса или же сам быть объявлен абстрактным:
public class Rectangle2 extends Figure2 < public Rectangle2(double dimension1, double dimension2) < super(dimension1, dimension2); >public double calculateArea() < System.out.println("B области четырехугольника."); return dimension1 * dimension2; >>
public class Triangle2 extends Figure2 < public Triangle2(double dimension1, double dimension2) < super(dimension1, dimension2); >public double calculateArea() < System.out.println("B области треугольника."); return dimension1 * dimension2 / 2; >>
У абстрактного класса не может быть объектов, но можно создать массив абстрактного класса, который будет содержать ссылки на объекты классов наследников:
public class FindAreas < public static void main(String[] args) < Figure[] figures = new Figure[3]; figures[0] = new Figure(10, 10); figures[1] = new Rectangle(10, 10); figures[2] = new Triangle(10, 10); for (Figure figure : figures) < double area = figure.caclulateArea(); System.out.println(area); >> >
Результат выполнения программы:
B области четырехугольника. 200.0 B области четырехугольника. 100.0 B области треугольника. 50.0
- Процедурное и объектно-ориентированное программирование
- Принципы ООП
- Классы и объекты
- Конструктор
- Ключевое слово this
- Перегрузка
- Стек и куча
- Передача объектов в методы
- Java varargs
- Рекурсия
- Сборщик мусора и метод finalize
- Наследование
- Ключевое слово super
- Модификаторы доступа
- Геттеры и сеттеры
- Переопределение методов
- Ключевое слово final
- Задания
Абстрактные классы и методы
Класс, содержащий абстрактные методы, называется абстрактным классом. Такие классы помечаются ключевым словом abstract.
Абстрактный метод не завершён. Он состоит только из объявления и не имеет тела:
abstract void yourMethod();
По сути, мы создаём шаблон метода. Например, можно создать абстрактный метод для вычисления площади фигуры в абстрактном классе Фигура. А все другие производные классы от главного класса могут уже реализовать свой код для готового метода. Ведь площадь у прямоугольника и треугольника вычисляется по разным алгоритмам и универсального метода не существует.
Если вы объявляете класс, производный от абстрактного класса, но хотите иметь возможность создания объектов нового типа, вам придётся предоставить определения для всех абстрактных методов базового класса. Если этого не сделать, производный класс тоже останется абстрактным, и компилятор заставит пометить новый класс ключевым словом abstract.
Можно создавать класс с ключевым словом abstract даже, если в нем не имеется ни одного абстрактного метода. Это бывает полезным в ситуациях, где в классе абстрактные методы просто не нужны, но необходимо запретить создание экземпляров этого класса.
В тоже время абстрактный класс не обязательно должен иметь только абстрактные методы. Напомню ещё раз, что если класс содержит хотя бы один абстрактный метод, то он обязан быть сам абстрактным.
Создавать объект на основе абстрактного класса нельзя.
// нельзя. даже не пытайтесь AbstractClass abstractClass = new AbstractClass();
Абстрактный класс не может содержать какие-либо объекты, а также абстрактные конструкторы и абстрактные статические методы. Любой подкласс абстрактного класса должен либо реализовать все абстрактные методы суперкласса, либо сам быть объявлен абстрактным. Короче, я сам запутался. Пойду лучше кота поглажу.
Я вернулся. Давайте напишем пример для абстрактного класса.
Допустим, мы хотим создать абстрактный класс СферическийКонь и не менее идиотский класс СферическийКоньВВакууме, наследующий от первого класса.
package ru.alexanderklimov.expresscourse; public abstract class SphericalHorse < // абстрактный метод ржать() abstract void neigh(); // абстрактный класс может содержать и обычный метод void gallop() < System.out.println("Куда прёшь?"); >> class SphericalHorseInVacuum extends SphericalHorse
Когда вы напишете такой код, то студия подчеркнёт второй класс красной волнистой линией и предложит реализовать обязательный метод, который определён в абстрактном классе.


Соглашаемся и дописываем в созданную заготовку свой код для метода.
@Override void neigh()
В главной активности напишем код для щелчка кнопки.
public void onClick(View view) < SphericalHorseInVacuum horse = new SphericalHorseInVacuum(); horse.neigh(); // на основе абстрактного метода horse.gallop(); // обычный метод >
Обратите внимание, что абстрактный класс может содержать не только абстрактные, но и обычные методы.
Раннее мы создавали класс Фигура, у которого был метод вычисления площади фигуры. Метод ничего не делал, так как невозможно вычислить площадь неизвестной фигуры. Поэтому, этот метод можно сделать абстрактным, а в классах, производных от Фигуры, переопределить данный метод.
// абстрактный класс Фигура abstract class Figure < double dim1; double dim2; Figure(double a, double b) < dim1 = a; dim2 = b; >// абстрактный метод для вычисления площади abstract double area(); > // Клас Треугольник class Triangle extends Figure < Triangle(double a, double b) < super(a, b); >// переопределяем метод double area() < return dim1 * dim2 / 2; >> // В активности public void onClick(View view) < // Figure figure = new Figure(10, 10); // так нельзя Triangle triangle = new Triangle(10, 8); Figure figure; // так можно, так как объект мы не создаем figure = triangle; mInfoTextView.append("Площадь равна " + figure.area()); >
Фигура — это абстрактное понятие и мы не можем создать универсальный метод для вычисления площади. Поэтому мы создаём другой класс Треугольник и пишем код, вычисляющий площадь треугольника (загляните в учебник геометрии). Также вы можете создать новый класс Прямоугольник и написать свой код для вычисления площади этой фигуры.
Вам вряд ли придётся часто создавать абстрактные классы для своих приложений, но встречаться с ними вы будете постоянно, например, классы AsyncTask, Service и др.
Кот — понятие тоже абстрактное. А вот ваш любимец Васька или Мурзик уже конкретный шерстяной засранец. По запросу «abstract cat» мне выдало такую картинку. Всегда интересовал вопрос, где художники берут такую травку? (это был абстрактный вопрос).
Что такое абстрактный метод
Кроме обычных классов в C# есть абстрактные классы . Зачем они нужны? Классы обычно представляют некий план определенного рода объектов или сущностей. Например, мы можем определить класс Car для преставления машин или класс Person для представления людей, вложив в эти классы соответствующие свойства, поля, методы, которые будут описывать данные объекты. Однако некоторые сущности, которые мы хотим выразить с помощью языка программирования, могут не иметь конкретного воплощения. Например, в реальности не существует геометрической фигуры как таковой. Есть круг, прямоугольник, квадрат, но просто фигуры нет. Однако же и круг, и прямоугольник имеют что-то общее и являются фигурами. И для описания подобных сущностей, которые не имеют конкретного воплощения, предназначены абстрактные классы.
Абстрактный класс похож на обычный класс. Он также может иметь переменные, методы, конструкторы, свойства. Единственное, что при определении абстрактных классов используется ключевое слово abstract . Например, определим абстрактный класс, который представляет некое транспортное средство:
abstract class Transport < public void Move() < Console.WriteLine("Транспортно средство движется"); >>
Транспортное средство представляет некоторую абстракцию, которая не имеет конкретного воплощения. То есть есть легковые и грузовые машины, самолеты, морские судна, кто-то на космическом корабле любит покататься, но как такового транспортного средства нет. Тем не менее все транспортные средства имеют нечто общее — они могут перемещаться. И для этого в классе определен метод Move, который эмулирует перемещение.
Но главное отличие абстрактных классов от обычных состоит в том, что мы НЕ можем использовать конструктор абстрактного класса для создания экземпляра класса. Например, следующим образом:
Transport tesla = new Transport();
Тем не менее абстрактные классы полезны для описания некоторого общего функционала, который могут наследовать и использовать производные классы:
Transport car = new Car(); Transport ship = new Ship(); Transport aircraft = new Aircraft(); car.Move(); ship.Move(); aircraft.Move(); abstract class Transport < public void Move() < Console.WriteLine("Транспортное средство движется"); >> // класс корабля class Ship : Transport < >// класс самолета class Aircraft : Transport < >// класс машины class Car : Transport
В данном случае от класса Transport наследуются три класса, которые представляют различные типы транспортных средств. Тем не менее они имеют общую черту — они могут перемещаться с помощью метода Move() .
Выше писалось, что мы не можем использовать конструктор абстрактного класса для создания экземпляра этого класса. Тем не менее такой класс также может определять конструкторы:
Transport car = new Car("машина"); Transport ship = new Ship("корабль"); Transport aircraft = new Aircraft("самолет"); car.Move(); // машина движется ship.Move(); // корабль движется aircraft.Move(); // самолет движется abstract class Transport < public string Name < get; >// конструктор абстрактного класса Transport public Transport(string name) < Name = name; >public void Move() =>Console.WriteLine($" движется"); > // класс корабля class Ship : Transport < // вызываем конструктор базового класса public Ship(string name) : base(name) < >> // класс самолета class Aircraft : Transport < public Aircraft(string name) : base(name) < >> // класс машины class Car : Transport < public Car(string name) : base(name) < >>
В данном случае в абстрактном классе Transport определен конструктор — с помощью параметра он устанавливает значение свойства Name, которое хранит название транспортного средства. И в этом случае производные классы должны в своих конструкторах вызвать этот конструктор.
Абстрактные члены классов
Кроме обычных свойств и методов абстрактный класс может иметь абстрактные члены классов, которые определяются с помощью ключевого слова abstract и не имеют никакого функционала. В частности, абстрактными могут быть:
- Методы
- Свойства
- Индексаторы
- События
Абстрактные члены классов не должны иметь модификатор private. При этом производный класс обязан переопределить и реализовать все абстрактные методы и свойства, которые имеются в базовом абстрактном классе. При переопределении в производном классе такой метод или свойство также объявляются с модификатором override (как и при обычном переопределении виртуальных методов и свойств). Также следует учесть, что если класс имеет хотя бы один абстрактный метод (или абстрактные свойство, индексатор, событие), то этот класс должен быть определен как абстрактный .
Абстрактные члены также, как и виртуальные, являются частью полиморфного интерфейса. Но если в случае с виртуальными методами мы говорим, что класс-наследник наследует реализацию, то в случае с абстрактными методами наследуется интерфейс, представленный этими абстрактными методами.
Абстрактные методы
Например, выше в примере с транспортными средствами метод Move описывает передвижение транспортного средства. Однако различные типы транспорта перемещаются по разному — ездят по земле, летят по воздуху, плывут на воде и т.д. В этом случае мы можем сделать метод Move абстрактным, а его реализацию переложить на производные классы:
abstract class Transport < public abstract void Move(); >// класс корабля class Ship : Transport < // мы должны реализовать все абстрактные методы и свойства базового класса public override void Move() < Console.WriteLine("Корабль плывет"); >> // класс самолета class Aircraft : Transport < public override void Move() < Console.WriteLine("Самолет летит"); >> // класс машины class Car : Transport < public override void Move() < Console.WriteLine("Машина едет"); >>
Transport car = new Car(); Transport ship = new Ship(); Transport aircraft = new Aircraft(); car.Move(); // машина едет ship.Move(); // корабль плывет aircraft.Move(); // самолет летит
Абстрактные свойства
Следует отметить использование абстрактных свойств. Их определение похоже на определение автосвойств. Например:
abstract class Transport < // абстрактное свойство для хранения скорости public abstract int Speed < get; set; >> // класс корабля class Ship: Transport < int speed; public override int Speed < get =>speed; set => speed = value; > > class Aircraft : Transport < public override int Speed < get; set; >>
В классе Transport определено абстрактное свойство Speed, которое должно хранить скорость транспортного средства. Оно похоже на автосвойство, но это не автосвойство. Так как данное свойство не должно иметь реализацию, то оно имеет только пустые блоки get и set. В производных классах мы можем переопределить это свойство, сделав его полноценным свойством (как в классе Ship), либо же сделав его автоматическим (как в классе Aircraft).
Отказ от реализации абстрактных членов
Производный класс обязан реализовать все абстрактные члены базового класса. Однако мы можем отказаться от реализации, но в этом случае производный класс также должен быть определен как абстрактный:
Transport tesla = new Auto(); tesla.Move(); // легковая машина едет abstract class Transport < public abstract void Move(); >// класс машины abstract class Car : Transport<> class Auto: Car < public override void Move() < Console.WriteLine("легковая машина едет"); >>
В данном случае класс Car не реализует абстрактный метод Move базового класса Transport и поэтому также определен как абстрактный. Однако любые неабстрактные классы, производные от Car, все равно должны реализовать все унаследованные абстрактные методы и свойства.
Пример абстрактного класса
Xрестоматийным примером является система геометрических фигур. В реальности не существует геометрической фигуры как таковой. Есть круг, прямоугольник, квадрат, но просто фигуры нет. Однако же и круг, и прямоугольник имеют что-то общее и являются фигурами:
// абстрактный класс фигуры abstract class Shape < // абстрактный метод для получения периметра public abstract double GetPerimeter(); // абстрактный метод для получения площади public abstract double GetArea(); >// производный класс прямоугольника class Rectangle : Shape < public float Width < get; set; >public float Height < get; set; >// переопределение получения периметра public override double GetPerimeter() => Width * 2 + Height * 2; // переопрелеление получения площади public override double GetArea() => Width * Height; > // производный класс окружности class Circle : Shape < public double Radius < get; set; >// переопределение получения периметра public override double GetPerimeter() => Radius * 2 * 3.14; // переопрелеление получения площади public override double GetArea() => Radius * Radius * 3.14; >
var rectanle = new Rectangle < Width = 20, Height = 20 >; var circle = new Circle < Radius = 200 >; PrintShape(rectanle); // Perimeter: 80 Area: 400 PrintShape(circle); // Perimeter: 1256 Area: 125600 void PrintShape(Shape shape) < Console.WriteLine($"Perimeter: Area: "); >
Абстрактный метод
Абстра́ктный ме́тод (или чистый виртуальный метод (pure virtual method — часто неверно переводится как чисто виртуальный метод)) — в объектно-ориентированном программировании, метод класса, реализация для которого отсутствует. Класс, содержащий абстрактные методы, также принято называть абстрактным (там же и пример). Абстрактные методы зачастую путают с виртуальными. Абстрактный метод подлежит определению в классах-наследниках, поэтому его можно отнести к виртуальным, но не каждый виртуальный метод является абстрактным.
Назначение
Абстрактный метод ничего не делает, но определяет параметры и возвращаемое значение.
Назначение абстрактных методов [1] :
- описание абстракции, которая не в более конкретизированном виде не может быть реализована;
- формальное (без реализации — есть или нет) удовлетворение требований о наличии статических методов при обращении к ним для прохождения проверки компилятора статической типизации, когда реализация их будет определена динамически (в процессе работы программы).
Примеры
С#
abstract type method_name(params);//определение в родительском классе override method_name(params). >;//определение в дочернем классе
C++
virtual void Abstr ( void ) = 0; // Чистая (пустая) виртуальная функция.
Delphi
procedure AbstractProcedure; abstract;
Литература
- Антон ЗлыгостевОбработка абстрактных методов в Delphi (рус.) // RSDN Magazine. — 2003. — № 2. АБСТРАКЦИЯ (от лат. abstraho – отвлекать, исключать, отделять) – необходимое условие познания путем формирования «вторичных образов» реальности (ее информационных моделей), в частности, таких, как восприятия, представления, понятия, теории и прочее. В процессе абстракции осуществляется выбор и обработка информации с целью заменить непосредственно данный эмпирический образ на другой, непосредственно не данный, но подразумеваемый и мыслимый как абстрактный объект и называемый обычно тем же термином «абстракция».
ОЧЕРК ИСТОРИИ. Современное понятие об абстракции восходит к Аристотелю, согласно которому абстрагирование – это метод намеренно одностороннего изучения реальности, субъективный прием мысленного разделения целого и полагание отдельно-сущими его частей. В принципе такое полагание не заключает «никакой ошибки» и объективно оправдано многообразием свойств (аспектов) целого, порою столь различных, что они не могут стать предметом, одной науки. Наука же, по Аристотелю, исследует общее, а общее познается посредством абстракции. Поэтому абстракция не только является основной предпосылкой научного познания, но и «создает науку». В этом смысле преходящие явления опыта важны не сами по себе, а в той мере, в какой они причастны к какой-либо абстракции. Аристотель также отличал эмпирические абстракции от теоретических, полагая, что последние необходимы там, где постигаемое мыслью и сама мысль неотделимы друг от друга (как, напр., в математике, где знание и предмет знания по существу совпадают).
См. также
Ссылки
- ↑Бадд Т. 14.6. Отложенные методы //Глава 14. Полиморфизм // Объектно-ориентированное программирование.
