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

а у нас есть несколько классов, которые имеют несколько методов с одинаковой сигнатурой, но не соответствуют объявленному интерфейсу Java. Например, обаJTextField а такжеJButton (среди нескольких других вjavax.swing.*) есть метод

public void addActionListener(ActionListener l)

Теперь предположим, что я хочу сделать что-то с объектами, которые имеют этот метод; затем я хотел бы иметь интерфейс (или, возможно, определить его сам), например,

  public interface CanAddActionListener {
      public void addActionListener(ActionListener l);
  }

чтобы я мог написать:

  public void myMethod(CanAddActionListener aaa, ActionListener li) {
         aaa.addActionListener(li);
         ....

Но, к сожалению, я не могу:

     JButton button;
     ActionListener li;
     ...
     this.myMethod((CanAddActionListener)button,li);

Этот акт будет незаконным. Компиляторзнает этоJButton не является a CanAddActionListenerпотому что класс не объявлен для реализации этого интерфейса ...Однако это "на самом деле" реализует это.

Иногда это доставляет неудобства - и сама Java изменила несколько базовых классов для реализации нового интерфейса, созданного из старых методов (String implements CharSequence, например).

Мой вопрос: почему это так? Я понимаю полезность объявления, что класс реализует интерфейс. Но в любом случае, глядя на мой пример, почему компилятор не может сделать вывод, что классJButton «удовлетворяет» объявлению интерфейса (заглядывая внутрь него) и принимает приведение? Это проблема эффективности компилятора или есть более фундаментальные проблемы?

Мое резюме ответовЭто тот случай, когда в Java можно было учесть некоторую «структурную типизацию» (что-то вроде утки, но проверено во время компиляции). Это не так. Помимо некоторых (неясных для меня) трудностей с производительностью и реализацией, здесь есть гораздо более фундаментальная концепция: в Java объявление интерфейса (и вообще всего) подразумевается не простоструктурный (иметь методы с этими подписями) носемантический: методы должны реализовывать определенное поведение / намерение. Итак, класс, которыйструктурно удовлетворяет некоторому интерфейсу (то есть имеет методы с требуемыми сигнатурами), не обязательно удовлетворяет егосемантически (крайний пример: вспомните «маркерные интерфейсы», которые даже не имеют методов!). Следовательно, Java может утверждать, что класс реализует интерфейс, потому что (и только потому, что) это было явно объявлено. Другие языки (Go, Scala) имеют другие философии.

Ответы на вопрос(6)

Ваш ответ на вопрос