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.

Правила использования ограничений методов в иерархиях типов

Следующие правила определяют, как ограничения метода должны использоваться в иерархиях типов.

  • Не добавляйте ограничения параметров метода для переопределённых или реализованных методов в дочернем типе.

  • Не добавляйте ограничения параметров метода для переопределённых или реализованных методов в дочернем типе, которые были объявлены с совпадающей сигнатурой в нескольких родительских типах.

  • Вы можете добавить ограничения возвращаемого значения в переопределённый или реализованный метод в дочернем типе.


Назад Вперёд Содержание
Логотип Oracle  Copyright © 2017, Oracle и/или её дочерних компаний. Все права защищены. Версия перевода 1.0.5 (Java EE Tutorial — русскоязычная версия)