Java - двоичная совместимость абстрактного класса и подклассов - PullRequest
6 голосов
/ 15 мая 2010

В Java я определяю абстрактный класс как с конкретными, так и с абстрактными методами в нем, и сторонние разработчики должны независимо разделять его на подклассы. Просто чтобы быть уверенным: есть ли какие-то изменения, которые я мог бы внести в абстрактный класс, совместимый с исходным кодом их классов, но не совместимый с двоичным кодом? Другими словами: после того, как они скомпилировали свои подклассы, могу ли я изменить абстрактный класс - кроме, например, добавление к нему абстрактного метода или удаление защищенного метода, вызываемого подклассами, которые, конечно, несовместимы с источником - таким образом, что может заставить их перекомпилировать свои подклассы?

Ответы [ 3 ]

9 голосов
/ 15 мая 2010

Если еще не поздно изменить вашу систему, я бы посоветовал вам сделать это. Переопределение обычно не является хорошим способом настройки функциональности, поскольку оно невероятно хрупкое. Например, если вы позже используете имя метода, которое использовали ваши клиенты (которое они теперь непреднамеренно автоматически переопределяют), то возможно, что переопределение полностью нарушит инварианты вашего класса. Обычно лучший способ обеспечить настройку - дать вашим клиентам интерфейс, ограниченный только настраиваемым поведением, и тогда у вас будет полностью конкретный класс, который зависит от экземпляра этого интерфейса, и соответствующим образом делегирует интерфейсу, когда это необходимо использовать настроенное поведение. Таким образом, ваш код и код вашего клиента будут полностью разделены, и они не будут мешать друг другу.

5 голосов
/ 15 мая 2010

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

Двоичная несовместимость также может быть введена, если вы добавили видимый метод и объявили его final, и этот метод столкнулся с сигнатурой какого-либо существующего метода в стороннем подклассе. Однако, если метод не является окончательным, существующий метод превратится в переопределение вашего (нового) метода, что может вызвать проблемы ... но не двоичную несовместимость.

Аналогичным образом, добавление новых видимых полей приведет к скрытию, может привести к сбивающему с толку поведению и нарушит сериализацию объекта. Но это не приведет к двоичной несовместимости.

В целом это указывает на то, что вам необходимо учитывать семантические проблемы приложения, а также простую двоичную совместимость. И система типов Java вам там не поможет.

Для полноты, есть другие вещи, которые вы могли бы сделать в своем коде, которые нарушали бы двоичную совместимость для сторонних классов:

  • уменьшить видимость вашего абстрактного класса и / или его методов,
  • изменить сигнатуры других классов, используемых в качестве параметров-результатов и типов исключений,
  • изменить цепочку суперклассов, которую расширяет ваш абстрактный класс, или внести несовместимые изменения в эти классы, или
  • измените дерево интерфейсов, которые реализует ваш абстрактный класс, или внесите несовместимое изменение в эти интерфейсы.
2 голосов
/ 15 мая 2010

Конечно.

Вы можете случайно использовать имя метода, которое они использовали, которое теперь внезапно переопределяется, что может привести к совершенно другим результатам.испортить сериализацию и т. д.

...