Во всех наших примерах с музыкальными инструментами (Instrument
), методы внутри базового класса Instrument
являются обязательно "фиктивными". При вызове этих методов возникают ошибки. Это происходит потому, что цель класса Instrument
— создание общего интерфейса для всех производных от него классов.
Основной причиной создания этого общего интерфейса является возможность представления различных подтипов различными способами. Он предоставляет нам базовый шаблон, который позволяет определять некоторые вещи как "общие" для всех производных классов. Чтобы проиллюстрировать эту идею, можно назвать класс Instrument
"абстрактным базовым классом" (АБК). Для работы со множеством классов через этот общий интерфейс требуется создать абстрактный класс. Все методы производных классов, соответствующие сигнатуре метода в базовом классе, могут быть вызваны через механизм динамической привязки (хотя, как было указано ранее, если имя метода совпадает с именем метода в базовом классе, но отличается набором аргументов, это может привести к перегрузке).Если есть абстрактный класс, такой как Instrument
, объекты этого класса практически всегда не имеют смысла. Другими словами, роль класса Instrument
заключается в том, чтобы представлять интерфейс, а не конкретную реализацию. Таким образом, создание объекта типа Instrument
не имеет смысла, и мы обычно должны запрещать пользователям делать это. Для достижения этой цели все методы внутри класса Instrument
могут выводить сообщение об ошибке. Однако такое решение замедляет получение информации до этапа выполнения программы и требует полного и надёжного тестирования со стороны пользователя. В любом случае, лучшим решением является выявление проблемы во время компиляции.Для решения этой задачи Java предлагает специальный механизм, называемый абстрактным методом. Это метод, который содержит только объявление, но не имеет тела метода. Ниже представлен синтаксис объявления абстрактного метода:
abstract void X();
Класс, содержащий один или несколько абстрактных методов, сам должен быть объявлен как abstract
. В противном случае компилятор сообщит об ошибке.
Что произойдет, если кто-то попытается создать объект от неполного абстрактного класса? Поскольку безопасно создать объект от абстрактного класса невозможно, компилятор сообщит об ошибке. Такой подход гарантирует "чистоту" абстрактного класса, и мы можем быть уверены, что он не будет использоваться некорректно. Если производить наследование от абстрактного класса и хотеть создать объект нового типа, то необходимо предоставить реализацию всех абстрактных методов, объявленных в базовом классе. В противном случае (что вполне возможно), производный класс также будет считаться абстрактным, а компилятор заставит нас пометить этот класс как «абстрактный» с помощью ключевого слова abstract
.
Даже если класс не содержит ни одного абстрактного метода, его можно объявить как «абстрактный». Это может оказаться полезным, когда нам требуется запретить создание экземпляров данного класса.Класс Instrument
легко можно преобразовать в абстрактный класс. Только некоторые из его методов станут абстрактными, поскольку превращение класса в абстрактный не требует автоматического объявления всех его методов как абстрактных. Вот как это выглядит:
Вот пример нашего модифицированного класса музыкальных инструментов, использующий абстрактные классы и методы:
//: Music4.java
// Абстрактные классы и методы
import java.util.*;
public abstract class Instrument4 {
protected int i; // Хранение, выделенное для каждого
public abstract void play();
public String what() {
return "Instrument4";
}
public abstract void adjust();
}
public class Wind4 extends Instrument4 {
@Override
public void play() {
System.out.println("Wind4.play()");
}
@Override
public String what() {
return "Wind4";
}
@Override
public void adjust() {}
}
public class Percussion4 extends Instrument4 {
@Override
public void play() {
System.out.println("Percussion4.play()");
}
@Override
public String what() {
return "Percussion4";
}
@Override
public void adjust() {}
}
public class Stringed4 extends Instrument4 {
@Override
public void play() {
System.out.println("Stringed4.play()");
}
@Override
public String what() {
return "Stringed4";
}
@Override
public void adjust() {}
}
public class Brass4 extends Wind4 {
@Override
public void play() {
System.out.println("Brass4.play()");
}
@Override
public void adjust() {
System.out.println("Brass4.adjust()");
}
}
public class Woodwind4 extends Wind4 {
@Override
public void play() {
System.out.println("Woodwind4.play()");
}
}
``` @Override
public String what() {
return "Дудочник4";
}
}
``````markdown
публичный класс Music4 {
// Независим от типа, поэтому новые типы,
// добавленные в систему, всё ещё работают правильно:
статический void tune(Instrument4 i) {
// ...
i.play();
}
статический void tuneAll(Instrument4[] e) {
для(int i = 0; i < e.length; i++)
tune(e[i]);
}
публичный статический void main(String[] args) {
Instrument4[] оркестр = новый Instrument4[5];
int i = 0;
// Поднятие типа при добавлении в массив:
оркестр[i++] = новый Wind4();
оркестр[i++] = новый Percussion4();
оркестр[i++] = новый Stringed4();
оркестр[i++] = новый Brass4();
оркестр[i++] = новый Дудочник4();
tuneAll(оркестр);
}
} ///:~
Абстрактный класс и его методы иногда оказываются очень полезными, так как они делают абстракцию класса явной истиной, четко сообщая пользователям и компилятору, как планируется использовать этот класс.
Помимо базового класса, действительно были внесены минимальные изменения.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )