5

Почему я не могу определить статический метод в интерфейсе Java?

13

ПРИМЕЧАНИЕ: Этот вопрос касается версии Java до 8. Начиная с Java 8, в интерфейсах разрешены статические методы. Однако их нельзя объявлять абстрактными (требовать переопределения) таким образом, как запрашивается в этом вопросе.

Почему я не могу определить статический метод в интерфейсе Java?

Вот пример:

public interface IXMLizable<T>
{
  static T newInstanceFromXML(Element e);
  Element toXMLElement();
}

Это не сработает. Но почему?

Одна из возможных проблем заключается в том, что произойдет, когда вы вызовете:

IXMLizable.newInstanceFromXML(e);

В этом случае, на мой взгляд, должен просто вызваться пустой метод (т.е. {}). Все подклассы будут вынуждены реализовать статический метод, так что они все будут в порядке при вызове статического метода. Так почему это невозможно?

Я, похоже, ищу ответ, который глубже, чем "потому что так устроена Java".

Существует ли какая-то технологическая причина, по которой статические методы не могут быть переопределены? То есть, почему разработчики Java решили сделать экземплярные методы переопределяемыми, но не статические?

Проблема с моим дизайном заключается в том, что я пытаюсь использовать интерфейсы для обеспечения соблюдения кодового соглашения.

То есть, цель интерфейса двояка:

  1. Я хочу, чтобы интерфейс IXMLizable позволял мне конвертировать классы, которые его реализуют, в XML-элементы (используя полиморфизм, это работает хорошо).

  2. Если кто-то хочет создать новый экземпляр класса, реализующего интерфейс IXMLizable, он всегда будет знать, что существует статический фабричный метод newInstanceFromXML(Element e).

Существует ли какой-либо другой способ обеспечить это, кроме как просто добавить комментарий в интерфейс?

5 ответ(ов)

0

Интерфейсы связаны с полиморфизмом, который по своей сути относится к экземплярам объектов, а не к классам. Поэтому использование ключевого слова static в контексте интерфейса не имеет смысла.

0

Сначала стоит отметить, что все решения по языкам программирования принимаются их создателями. В мире программной инженерии, определения языков или разработки компиляторов/интерпретаторов нет ничего, что бы запрещало статическим методам быть частью интерфейса. Я сам создавал несколько языков и писал компиляторы для них — это всего лишь вопрос определения осмысленной семантики. Я бы утверждал, что семантика статического метода в интерфейсе весьма ясна, даже если компилятор должен откладывать разрешение метода до времени выполнения.

Во-вторых, то, что мы вообще используем статические методы, подразумевает наличие обоснованной необходимости в шаблоне интерфейса, который включает статические методы — могу сказать за себя, я регулярно использую статические методы.

Скорее всего, главный ответ заключается в том, что на момент определения языка не было осознанной необходимости в статических методах в интерфейсах. Java за эти годы сильно развилась, и этот вопрос, судя по всему, стал вызывать интерес. То, что его рассматривали для Java 7, указывает на то, что он достиг уровня интереса, который может привести к изменениям в языке. Лично я буду рад, когда мне больше не придется создавать объект только для того, чтобы вызвать свой нестатический метод для доступа к статической переменной в экземпляре подкласса...

0

В Java 8 в интерфейсы были добавлены статические методы, что позволяет упростить создание экземпляров классов, реализующих интерфейсы. В вашем случае вы можете использовать статический метод в интерфейсе IXMLizable, чтобы создавать новые экземпляры, исходя из XML-элемента, без необходимости реализовывать отдельный фабричный паттерн.

Вот пример вашего интерфейса с добавленным статическим методом:

public interface IXMLizable {

    /**
     * Конвертирует реализующий объект в XML-элемент.
     *
     * @return Элемент, представляющий реализующий объект.
     */
    public Element toXMLElement();

    /**
     * Статический метод-фабрика для создания нового экземпляра класса, реализующего IXMLizable, из XML-элемента.
     *
     * @param e XML-элемент, из которого нужно создать экземпляр IXMLizable.
     * @return Экземпляр класса, реализующего IXMLizable, инициализированный из данного XML-элемента.
     */
    public static IXMLizable create(Element e) {
        return new MyIXMLizable(e);
    }
}

Если вам все же нужно следовать класическому паттерну фабрики, можно создать его в следующем виде:

public interface IXMLizable {
    public Element toXMLElement();
}

public interface IXMLizableFactory<T extends IXMLizable> {
    public T newInstanceFromXML(Element e);
}

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

0

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

0

Вопрос о том, почему статические методы не могут быть переопределены, часто вызывает интерес и требует понимания основ ООП (объектно-ориентированного программирования).

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

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

Другими словами, если вам нужно вызывать метод без экземпляра класса, но при этом хотите сохранить возможность различать поведение на основе экземпляров, вам стоит использовать виртуальные методы или интерфейсы, которые обеспечивают необходимую гибкость через полиморфизм.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь