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

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

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

Это добавляет Реализации.. и необходимые методы к КАЖДОМУ КЛАССУ Вы объявляете. Довольно грубо, isnt'it?

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

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

Моя идея была к, расширяет java.lang. Объект.. но Вы не можете. (право?)
Другие идеи?

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

6
задан Fabio F. 18 May 2010 в 08:23
поделиться

6 ответов

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

6
ответ дан 8 December 2019 в 14:41
поделиться

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

Например, JDK предоставляет класс PropertyChangeSupport , который можно использовать для управления слушателями PropertyChangeListener и запуском событий PropertyChangeEvent . В ситуациях, когда вы хотите написать класс, который запускает события PropertyChangeEvent , вы можете встроить переменную экземпляра 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);
  }
}
3
ответ дан 8 December 2019 в 14:41
поделиться
  • вы можете расширить Object - каждый класс расширяет его.
  • похоже, вам нужно что-то вроде множественного наследования - в Java такого нет
  • если вы хотите добавить функциональность, используйте композицию объектов. Т.е.,

    YourClass extends Whatever implements ObjectWithRoles {
     private RoleHandler roleHandler;
     public RoleHandler getRoleHandler() {...} // определяется интерфейсом
    }
    

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

3
ответ дан 8 December 2019 в 14:41
поделиться

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

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

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

2
ответ дан 8 December 2019 в 14:41
поделиться

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

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

1
ответ дан 8 December 2019 в 14:41
поделиться

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

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

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

1
ответ дан 8 December 2019 в 14:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: