Anatoly Vorobey (avva) wrote,
Anatoly Vorobey
avva

Category:

интерфейсы

Это будет интересно только программистам.

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

Предположим, у нас есть интерфейс Foo и класс Bar. Предположим, в классе есть определения всех методов, которые перечислены в интерфейсе, с правильными аргументами, типами возврата и другими атрибутами. Значит, компилятор может этот факт в любой момент проверить напрямую, сверив определения класса и интерфейса (причем класс может быть в скомпилированной форме). В любом месте, где мы хотим использовать объект класса Bar (или его подкласса), а ожидают интерфейс Foo - например, в списке аргументов какого-то метода - сейчас компилятор проверяет правильность подстановки, основываясь на том, что в определении Bar написано "implements Foo". Но если бы не было написано, он все равно мог бы проверить правильность подстановки, просто напрямую сравнив типы методов класса и интерфейса.

(Я что-то упускаю тут или правильно все описал?)

Если это ключевое слово не нужно, зачем же оно есть? Зачем дизайнеры языка заставляют программиста специально написать, что класс Bar воплощает интерфейс Foo, если это не дает компилятору новой информации? Я бы сказал - по двум причинам; во-первых, из идеологических соображений, чтобы заставить программиста иметь в голове стройную картинку того, кто что воплощает. Во-вторых, чтобы была дополнительная проверка совместимости класса с интерфейсом в момент определения класса, а не только в момент его использования в качестве интерфейса. Без этой проверки, скажем, ошибка в определении класса, делающая его несовместимым с интерфейсом, обнаружилась бы только в момент использования класса там, где требуется интерфейс, а не во время компиляции самого класса с интерфейсом.

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

См. также интересную статью JavaGI: Generalized Interfaces for Java, которая натолкнула меня на эту нехитрую мысль. JavaGI - интересная попытка внести в Джаву идею type classes из Haskell. Предположим, у вас есть интерфейс и класс, скорее всего из разных источников (возможно, только в скомпилированном виде), причем класс как бы воплощает все, что нужно интерфейсу, но не под теми же именами, и возможно с некоторыми тривиальными изменениями. Обычное решение, опять-таки - промежуточный класс, Adapter pattern. Вместо этого предлагается новый синтаксис, который совмещает класс и интерфейс вместе, "объясняя" компилятору, как воплотить методы интерфейса в терминах методов класса, так, что после этого компилятор может подставлять объект класса туда, где нужен интерфейс, как обычно. Нет умножения сущностей в виде ненужного по сути дела промежуточного класса; вместе с тем сохраняются все проверки типизации, обычные для Джавы. Довольно любопытная идея.

Subscribe
  • Post a new comment

    Error

    default userpic

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 95 comments
Previous
← Ctrl ← Alt
Next
Ctrl → Alt →
Previous
← Ctrl ← Alt
Next
Ctrl → Alt →