Ответ
В Java класс может наследоваться только от одного класса — будь то абстрактный или обычный. Это принцип единого наследования классов. Однако класс может реализовывать неограниченное количество интерфейсов.
Почему это важно для тестирования (QA): Понимание этого ограничения помогает при анализе кода и проектировании тестов. Например, если я вижу сложную иерархию наследования в коде, я понимаю, что:
- Мокать (mock) такие зависимости в unit-тестах может быть сложнее из-за жесткой связности.
- Нарушение этого правила (попытка множественного наследования) приведет к ошибке компиляции, которую можно выявить на этапе статического анализа или при запуске CI-пайплайна.
- Для тестирования классов, использующих наследование, важно покрыть тестами не только методы самого класса, но и унаследованное поведение, которое может быть переопределено.
Пример, который я мог бы встретить в коде проекта:
// Абстрактный класс, определяющий общее поведение для тестовых данных
abstract class TestDataGenerator {
abstract String generateName();
public String getCommonPrefix() { return "TEST_"; }
}
// Класс, от которого мы НЕ можем унаследоваться одновременно
abstract class DataValidator {
abstract boolean validate(String data);
}
// КОРРЕКТНО: Наследование от одного абстрактного класса
class UserTestDataGenerator extends TestDataGenerator {
@Override
String generateName() { return getCommonPrefix() + "User"; }
}
// НЕКОРРЕКТНО: Вызовет ошибку компиляции. Вместо этого нужно использовать интерфейсы или композицию.
// class AdvancedTestDataGenerator extends TestDataGenerator, DataValidator { } // ОШИБКА!
На практике в QA-автоматизации мы чаще используем композицию и интерфейсы для создания гибких и легко тестируемых вспомогательных классов.