public class Person {
...
public void setPhone(String phone) { ... }
}
public class Employee extends Person {
...
@Override
public void setPhone(@Verified String phone) { ... }
}
Java Platform, Enterprise Edition (Java EE) 8 Учебник по Java EE |
Назад | Вперёд | Содержание |
Если вы добавляете ограничения валидации к объектам в иерархии наследования, будьте особенно внимательны, чтобы избежать непреднамеренных ошибок при использовании дочерних типов.
Для данного типа дочерние типы должны иметь возможность замены без возникновения ошибок. Например, если у вас есть класс Person
и его дочерний класс Employee
, который расширяет Person
, вы сможете использовать объекты Employee
, где бы вы ни использовали объекты Person
. Если Employee
переопределяет метод в Person
путём добавления ограничений параметров метода, код, который корректно работает с объектами Person
, может генерировать исключения валидации с объектами Employee
.
Следующий код показывает некорректное использование ограничений параметров метода в иерархии классов:
public class Person {
...
public void setPhone(String phone) { ... }
}
public class Employee extends Person {
...
@Override
public void setPhone(@Verified String phone) { ... }
}
При добавлении ограничения @Verified
в Employee.setPhone
параметры, которые были валидными для Person.setPhone
, не будут таковыми для Employee.setPhone
. Это называется усилением предварительных условий (или параметров метода) метода дочернего типа. Вы не можете усиливать предварительные условия вызовов методов дочернего типа.
Аналогично, возвращаемые значения из вызовов методов не должны быть ослаблены в дочерних типах. В следующем коде показано некорректное использование ограничений на возвращаемые значения метода в иерархии классов:
public class Person {
...
@Verified
public USPhoneNumber getPhone() { ... }
}
public class Employee extends Person {
...
@Override
public USPhoneNumber getPhone() { ... }
}
В этом примере метод Employee.getPhone
удаляет ограничение @Verified
для возвращаемого значения. Возвращаемые значения, которые не прошли бы проверку при вызове Person.getEmail
, разрешены при вызове Employee.getPhone
. Это называется ослаблением постусловий (то есть возвращаемых значений) дочернего типа. Вы не можете ослабить постусловия вызова метода дочернего типа.
Если ваша иерархия типов усиливает предусловия или ослабляет постусловия вызовов методов дочернего типа, во время выполнения Bean Validation будет сгенерирован javax.validation.ConstraintDeclarationException
.
Классы, реализующие несколько интерфейсов, в каждом из которых имеется метод с совпадающей сигнатурой, должны знать об ограничениях, применяемых к реализуемым интерфейсам, чтобы избежать усиления предварительных условий. Например:
public interface PaymentService {
void processOrder(Order order, double amount);
...
}
public interface CreditCardPaymentService {
void processOrder(@NotNull Order order, @NotNull double amount);
...
}
public class MyPaymentService implements PaymentService,
CreditCardPaymentService {
@Override
public void processOrder(Order order, double amount) { ... }
...
}
В этом случае MyPaymentService
имеет ограничения из метода processOrder
в CreditCardPaymentService
, но код клиента, который вызывает PaymentService.processOrder
не ожидает этих ограничений. Это ещё один пример усиления предварительных условий подтипа, который приведёт к ConstraintDeclarationException
.
Следующие правила определяют, как ограничения метода должны использоваться в иерархиях типов.
Не добавляйте ограничения параметров метода для переопределённых или реализованных методов в дочернем типе.
Не добавляйте ограничения параметров метода для переопределённых или реализованных методов в дочернем типе, которые были объявлены с совпадающей сигнатурой в нескольких родительских типах.
Вы можете добавить ограничения возвращаемого значения в переопределённый или реализованный метод в дочернем типе.
Назад | Вперёд | Содержание |