Добавить удалить ссылку на ListView — как ссылаться на внешний анонимный класс из внутреннего анонимного класса

#java #wicket

#java #калитка

Вопрос:

Wicket ListView предоставляет removeLink для добавления с помощью ListItem. Реализация метода removeLink в исходном коде класса ListView является:

 public final Link removeLink(final String id, final ListItem item)
{
    return new Link(id)
    {
        private static final long serialVersionUID = 1L;

        /**
         * @see org.apache.wicket.markup.html.link.Link#onClick()
         */
        public void onClick()
        {
            addStateChange(new Change()
            {
                private static final long serialVersionUID = 1L;

                final int oldIndex = getList().indexOf(item.getModelObject());
                final Object removedObject = item.getModelObject();

                public void undo()
                {
                    getList().add(oldIndex, removedObject);
                }

            });

            item.modelChanging();

            // Remove item and invalidate listView
            getList().remove(item.getModelObject());

            ListView.this.modelChanged();
            ListView.this.removeAll();
        }
    };
}
  

Теперь, если я добавлю ссылку на ListItem и переопределю метод onClick (), как указано выше, и добавлю к нему дополнительные функциональные возможности, как я могу переопределить этот фрагмент :

 ListView.this.modelChanged();
ListView.this.removeAll();
  

Поскольку создание экземпляра объекта ListView выполняется Анонимным классом ListView и то же самое для Ссылки.

 add(new ListView("listId", list) {
    protected void populateItem(ListItem item) {
         item.add(new Link("linkId") {
             public void onClick() {
                 // how can I define
                 // ListView.this.modelChanged();
                 // ListView.this.removeAll();
                 // here?
             }
         });
    }
});
  

То есть как сослаться на внешний анонимный класс из внутреннего анонимного класса? Вызывается ли метод анонимного внешнего класса (хотя он является внутренним) из анонимного внутреннего класса этого внешнего класса в целом? Возможно ли это на Java?

Комментарии:

1. Вы пробовали это? Это скомпилировалось?

2. @Ravi Wallau нет, это не компилировалось.

Ответ №1:

Вы можете использовать Component.findParent(class) :

 ListView<?> listView = findParent(ListView.class);
listView.modelChanged();
listView.removeAll();
  

Или вы могли бы просто вызвать super.onClick() свой onClick() метод.

Комментарии:

1. Я попробовал это.getParent() в методе onClick (). Но это не удается. И ссылка extend AbstractLink, которая дополнительно расширяет WebMarkupContainer, в super (ах) нет метода onClick(). Хотя onClick() ссылки является абстрактным. Не так ли? Как я могу вызвать super.onClick()? Как насчет вызова метода анонимного внешнего класса (хотя он и внутренний) из анонимного внутреннего класса этого внешнего класса в целом? Возможно ли это в Java?

2. @Tapas а) что означает «сбой»? Это стандартный метод, и он всегда работает б) насчет super, моя ошибка, я думал, ты переопределяешь removeLink()

3. 1) извините за мою ошибку. Поскольку я попробовал this.getParent (), который возвращал ListItem, так что теперь я сделал (ListView) this.getParent().getParent() и это сработало. Также (ListView) this.findParent(ListView.class ) работал нормально. Итак, оба они сработали. Спасибо. 2) У меня есть вопрос относительно фрагмента кода, который я привел в своем первом сообщении. Зачем вызывать ListView.removeAll(). После добавления StateChange в Link мы вызвали ListItem.modelChanging(), затем удалили элемент и вызвали modelChanged(), какая польза от removeAll()? 3) Что привело к перезагрузке страницы? Спасибо.

4. @Tapas пожалуйста: в комментариях нет вопросов. задайте новый вопрос

Ответ №2:

Я верю, что приведенный ниже код сработает — объявленные переменные доступны из внутреннего класса, если они объявлены окончательными, поэтому вы можете объявить переменную, содержащую экземпляр ListView, и использовать ее из вашего внутреннего класса, как я сделал в примере ниже. Пожалуйста, обратите внимание, что я не компилировал этот код, но я не вижу причин, по которым он не будет работать. Просто помните, что переменная должна быть объявлена окончательной.

 add(new ListView("listId", list) {
    protected void populateItem(ListItem item) {
         final ListView lv = this;
         item.add(new Link("linkId") {
             public void onClick() {
                 lv.modelChange();
                 lv.removeAll();
             }
         });
    }
});
  

Комментарии:

1. Спасибо. Предоставленное вами решение сработало отлично. Итак, я предполагаю, что таким образом в общем случае мы можем вызвать метод внешнего анонимного класса из внутреннего анонимного класса! Не так ли?

2. Если у вас есть возможность объявить переменную, как у меня, тогда да, это правильный способ сделать это.

Ответ №3:

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

Комментарии:

1. Это разумный совет во многих случаях, но непрактичный с Wicket. Поведение простых компонентов (таких как текстовый заполнитель или компонент формы) часто определяется переопределяющими методами из родительских классов. Если бы вы создали соответствующий класс для каждого из них, у вас были бы десятки классов даже для простых страниц.

2. Я тоже использую анонимный внутренний класс в Swing. И я люблю это использовать.

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

4. @perilandmishap Обратите внимание, что я не говорил в каждом случае, и я не говорил, что вы должны использовать классы верхнего уровня. Действительно, у анонимного внутреннего класса есть некоторое преимущество перед именованным внутренним классом, но все это теряется в тот момент, когда вы пытаетесь делать нетривиальные вещи.