2015-04-26 5 views
6

Есть ли модуль расширения groovy, имеющий гибридную форму функции наследования Java? Почему модуль расширения должен быть объявлен как статический?Модуль расширения Groovy по сравнению с наследованием java

+0

Мысль о модулях расширения в терминах наследования - плохая идея. Они расширяют определенный класс с дополнительным поведением: поэтому они изменяют существующую иерархию наследования, а не вносят вклад в это ... но их контекст действительно сосредоточен на одном классе (так что опять же, игнорируйте наследование). Другие языки имеют аналогичную конструкцию как часть определения типа первого класса (Go, Scala, Kotlin ...). Они являются статичными, потому что они определены вне среды привязки среды выполнения :, поэтому вместо этого этот экземпляр получает аргумент (опять же похожий на подход других языков). –

ответ

0

Короткий ответ Я думаю, да. Чуть трудно ответить четко, поскольку наследование методов расширения полностью выполняется средой выполнения (и статическим компилятором). Таким образом, это не имеет никакого отношения к тому, как Java наследует.

Чтобы ответить на второй вопрос ... Они являются статическими, потому что для ситуаций, в которых вам нужно состояние, вы обычно используете мета-класс. Методы расширения изначально считаются удобными методами или делают API более Groovy. Таким образом, они представляют собой особую форму методов, добавленных в мета-класс. Вы можете видеть их как упрощенную версию. Но это также означает, что у них нет всех способностей. Внедрение методов расширения, которые могут поддерживать локальное состояние на основе «self» -объекта (в основном, какие поля/свойства будут делать), на самом деле сложно сделать эффективными ... но вы всегда можете использовать для каждого класса мета классов.

0

Для всех обширных целей они являются синтаксическим сахаром, так что статический метод кажется более похожим на ООП. Наследования нет, потому что статические методы в Java и Groovy не участвуют в наследовании (то есть классы не наследуют статические методы).

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

Однако я считаю, что существуют языки, которые позволяют определять методы за пределами окружающего класса и выполнять какое-то наследование, но не многие из них (я считаю, что CLOS и Dylan do). Кроме того, они представляют собой много языков, которые, как представляется, позволяют добавлять методы, но тип «объекта» фактически изменен/скрыт для какого-либо другого типа. Это называется адхок-полиморфизмом (например, Clojure, Haskell, своего рода Golang и своего рода Scala), но опять-таки не имеет ничего общего с инклюзивным полиморфизмом (наследование Java).

0

К сожалению reference documentation и другие документы не определяют семантику методов расширения:

  • Q. Можно ли переопределить методы экземпляра?
    Я тестировал методы расширения через use Методы категорий и metaClass методы expando. Ни один из подходов не отменяет методы экземпляра. Я не тестировал extension modules, установленный через module descriptor.
  • В. Могут ли они быть переопределены методами расширения на подклассах?
    Я тоже это испытал. use методы и metaClass методы расширения не переопределяются методами расширения на подклассах.
  • В. Можно ли назвать унаследованные методы super?
    Нет, поскольку они реализованы с помощью методов static.
  • В. Могут ли они назвать частные методы?
    Эксперименты показали, что они могут, на удивление.
  • В. Могут ли они получить доступ к переменным частного экземпляра?
    Нет, поскольку они реализованы с помощью методов static.
  • Q. Являются ли они вызываемыми из Java-методов?
    Возможно, if the extension module is on the classpath при компиляции вызывающего кода. Я не проверял.

Заключение:Методы расширения не являются формой наследования. Они кажутся динамической формой Universal Function Call Syntax (UFCS), то есть, когда язык не может найти способ variable.foo(arguments), он ищет статическую функцию расширения foo(variable, arguments) для вызова. [Пожалуйста, исправьте мою гипотезу, если не так!]

Вы спрашивали, почему они определены как static. Это похоже на семантику: статическая функция, которая не участвует в наследовании, хотя ее синтаксис вызова делает его похожим на удобный вызов метода.

Вы можете написать метод расширения, например, метод экземпляра, используя аннотацию @groovy.lang.Category. Это делает преобразования АСТ во время компиляции, чтобы превратить его в подходящий статический метод.

Также см. Groovy traits. Это является формой (mixin) наследования.