Java: расширяющий класс Object - PullRequest
6 голосов
/ 18 мая 2010

Я пишу (ну, я заканчиваю) «расширение» 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.lang.Object .. но вы не можете. (Правильно?)
Другие идеи?

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

Ответы [ 6 ]

6 голосов
/ 18 мая 2010

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

3 голосов
/ 18 мая 2010

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

Например, JDK предоставляет класс PropertyChangeSupport, который может использоваться для управления PropertyChangeListener с и стрельбой PropertyChangeEvent с. В ситуациях, когда вы хотите написать класс, который запускает PropertyChangeEvent s, вы можете встроить переменную экземпляра 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 голосов
/ 18 мая 2010
  • вы можете расширить Object - каждый класс расширяет его.
  • вам, кажется, нужно что-то вроде множественного наследования - в Java такого нет
  • , если вы хотите добавить функциональность, используйте композицию объектов. Т.е.

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

И тогда все методы помещаются в RoleHandler

2 голосов
/ 18 мая 2010

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

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

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

1 голос
/ 18 мая 2010

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

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

1 голос
/ 18 мая 2010

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

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

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

...