Java: расширение класса объектов

Я пишу (ну, завершаю) "расширение" Java, которое поможет ролевому программированию.
Я перевожу свой код на Java-код с помощью javacc. Мои компиляторы добавляют к каждому объявленному классу некоторый код. Вот пример, чтобы быть более ясным:

MyClass extends String implements ObjectWithRoles { //implements... is added
    /*Added by me */
    public setRole(...){...}
    public ...
    /*Ends of stuff added*/
    ...//myClass stuff
}

Он добавляет инструменты.. и необходимые методы для каждого класса, который вы объявляете. Довольно грубо, не так ли?

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

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

моя идея заключалась в расширении java.ленг.Объект.. но ты не можешь. (верно?)
Другие идеи?

Я новичок здесь, но я следую за этим сайтом, поэтому спасибо за чтение и все ответы, которые вы даете! (Прошу прощения за английский, я итальянский)

6 ответов


если это только как "исследовательский" проект, в котором вы хотите изучить, как такое расширение будет работать, вы можете обеспечить свою собственную реализацию Object класса. Просто скопируйте существующую реализацию объекта, добавьте свой setRole метод etc, и дайте -Xbootclasspath:.:/usr/lib/jvm/java-6-sun/jre/lib/rt.jar как параметр команды java. (Я буду искать api-классы в . прежде чем смотреть в реальном rt.jar.)


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

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

public class MyClass extends MySuperClass {
  private final PropertyChangeSupport support;

  public MyClass() {
    this.support = new PropertyChangeSupport(this);
  }

  public void addPropertyChangeListener(PropertyChangeListener l) {
    support.addPropertyChangeListener(l);
  }

  protected void firePropertyChangeEvent() {
    PropertyChangeEvent evt = new ...
    support.firePropertyChangeEvent(evt);
  }
}

  • вы можете продлить Object - каждый класс расширяет его.
  • вам, похоже, нужно что - то вроде множественного наследования-в Java нет такой вещи
  • если вы хотите добавить функциональность, используйте композицию объекта. Т. е.,

    YourClass extends Whatever implements ObjectWithRoles {
        private RoleHandler roleHandler;
        public RoleHandler getRoleHandler() {..} // defined by the interface
    }
    

и затем все методы помещаются в RoleHandler


Если вы говорите о добавлении роли ко всем вашим объектам, я бы также рассмотрел решение на основе аннотаций. Вы бы аннотировали свои классы чем-то вроде @Role("пользователь"). В другом классе вы можете извлечь это значение роли и использовать его.

Я думаю, что ему понадобится аннотация с удержание во время выполнения и вы можете проверить, время выполнения, присутствует ли аннотация с помощью отражения и получить эту аннотацию с помощью getAnnotation. Я чувствую, что это было бы намного чище, чем автоматическое расширение всех ваших классов.

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


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

кроме того, как было указано в комментариях, строка объявляется "окончательной" и, следовательно, не может быть расширена. Таким образом, вы должны действительно рассмотреть решение, в котором вы делегируете/украшаете объекты. Например, у вас может быть какой-то объект, который обертывает строку и предоставляет доступ к строке через getString () или toString (), но затем добавляет дополнительную функциональность поверх класса String.

Если вы просто хотите связать некоторые объекты с дополнительными атрибутами, используйте карта (например,HashMap).


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

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