Я пишу (хорошо, завершаясь) "расширение" 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. Объект.. но Вы не можете. (право?)
Другие идеи?
Я являюсь новым здесь, но я следую за этим сайтом так спасибо за чтение и все ответы, которые Вы даете! (Я приношу извинения за английский язык, я итальянец),
Если это всего лишь «исследовательский» проект, в котором вы хотите изучить, как будет работать такое расширение, вы можете предоставить свою собственную реализацию класса Object
. Просто скопируйте существующую реализацию объекта, добавьте свой метод setRole
и т.д. и укажите -Xbootclasspath:.: / Usr / lib / jvm / java-6-sun / jre / lib / rt.jar
в качестве параметра java-команды. (Я буду искать api-классы в .
, прежде чем искать в реальном rt.jar
.)
Для решения этой проблемы вам следует подумать об использовании композиции, а не наследования; таким образом вы можете предоставить необходимую вам функциональность, не тратя свой «единственный шанс» при наследовании.
Например, 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);
}
}
Object
- каждый класс расширяет его. если вы хотите добавить функциональность, используйте композицию объектов. Т.е.,
YourClass extends Whatever implements ObjectWithRoles {
private RoleHandler roleHandler;
public RoleHandler getRoleHandler() {...} // определяется интерфейсом
}
А затем все методы помещаются в RoleHandler
Если вы говорите о добавлении роли ко всем вашим объектам, я бы также рассмотрел решение на основе аннотаций. Вы бы аннотировали свои классы чем-то вроде @Role("User"). В другом классе вы можете извлечь значение роли и использовать его.
Я думаю, что для этого потребуется аннотация с runtime retention, и вы можете проверить во время выполнения, присутствует ли аннотация, используя отражение, и получить эту аннотацию с помощью getAnnotation. Мне кажется, что это будет гораздо чище, чем расширять все классы автоматически.
Я полагаю, что есть несколько фреймворков, которые используют именно такое решение, поэтому где-то должен быть пример кода.
То, что вы действительно хотите сделать, это исправление обезьяны , то есть изменение поведения существующих классов без изменения их кода.
К сожалению, Java не поддерживает это, а также такие вещи, как миксины , которые можно было бы использовать в качестве альтернативы. Так что, если вы не захотите переключиться на более динамичный язык, такой как Groovy, вам придется жить с менее элегантными решениями, такими как композиция.
Если вы делаете то, что делаете, то наследование, вероятно, не является правильная идиома. Вы можете рассмотреть шаблон декоратора, посредством которого вы создаете класс, который принимает в качестве параметра какой-то другой класс с меньшей функциональностью и добавляет к нему некоторые дополнительные функции, делегируя существующему классу функциональность, которая уже существует. Если реализация является общей для многих ваших декораторов, вы можете подумать о том, чтобы поместить эту функциональность в класс, который может быть общим и которому вы можете делегировать все свои декораторы. В зависимости от того, что вам нужно, двойная отправка или отражение могут быть подходящими для создания похожих, но не совсем одинаковых декораторов для большого разнообразия классов.
Кроме того, как было указано в комментариях, String объявлен "окончательным" и, следовательно, не может быть расширен. Итак, вам действительно стоит подумать о решении, посредством которого вы делегируете / украшаете объекты. Например, у вас может быть какой-то объект, который обертывает строку и предоставляет доступ к строке через getString () или toString (), но затем добавляет дополнительные функции поверх класса String.
Если вы просто хотите связать некоторые объекты с дополнительными атрибутами, используйте карту (например, HashMap ).