Я могу гарантировать ввод на классе И интерфейсе аргумента?

Я пользуюсь библиотекой GWT. Существует базовый класс под названием Виджет, которому наследовались все Виджеты. Некоторые Виджеты реализуют определенные интерфейсы (например, HasText), другие не делают. Иногда я хочу гарантировать, что что-то передаваемое как аргумент функции имеет определенный класс И реализует определенный интерфейс.

Например, я хочу иметь функцию, которая берет аргумент X, где X имеет Виджет типа класса И интерфейсного типа HasText. Я хочу иметь это поведение, потому что только Виджеты могут быть добавлены к Контейнерам макетов, и HasText указывает полный набор поведений, в которых я на самом деле нуждаюсь от упомянутого Виджета.


В форме псевдокода это могло бы быть:

public void fx(I_AM_A_Widget_AND_IMPLEMENT_INTERFACE_HasText x){
    //do stuff with x, which is guaranteed to be a Widget AND implement HasText
}

Это находится любым возможным путем в Java? Если существует несколько способов сделать так, есть ли предпочтительный/лучше путь?

5
задан Michael Easter 19 February 2010 в 03:22
поделиться

3 ответа

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

public class Example<Editable extends Widget & HasText> {
  private Editable editor = null;

  //do stuff in various methods (including the constructor) with the 
  //editor variable and the Editable type.
}

Я выбрал это решение по нескольким причинам.

  1. Два вышеупомянутых решения требуют использования методов (boilerplate), которые на самом деле не относятся к бизнес-функциональности, но вместо этого связаны с обходом ограничений языка.
  2. Анон, ваше решение верно, но у меня возникла проблема, связанная с невозможностью объявить переменную, которая бы хранила ссылку на общий объект, возвращаемый вашим методом. Я полагаю, что это происходит потому, что общий объект, возвращаемый вашим методом, существует только на уровне метода, а не класса. Возможно, я упустил какой-то синтаксис, который позволил бы мне объявлять переменные с родовыми свойствами?
  3. Yishai, ваше решение тоже работает, но тогда у меня возникает проблема объявления отдельного метода в каждом интерфейсе, поддержку которого я хочу гарантировать, это кажется громоздким.
  4. Эти ограниченные типы, объявленные в классе "header", должны быть объявлены только один раз. Кажется, что это самое краткое объявление общих ограниченных типов, доступное в Java.
  5. Вы можете объявить более одного ограниченного типа в классе "header".
  6. Если вы используете только этот метод, все потенциальные ограниченные типы будут объявлены в одном и том же месте вашего кода.

Объявление ограниченных типов в заголовке класса - это лучшее решение, с которым я сталкивался. Мне было бы интересно узнать, есть ли способ постоянно объявлять (чтобы к нему можно было обращаться в разных классах) ограниченные типы, а не объявлять их в каждом классе.

0
ответ дан 14 December 2019 в 04:36
поделиться

Здесь вы могли бы использовать универсальный метод:

public <T extends Widget & HasText> void fx(T x)

Компилятор автоматически определит тип T, поэтому при вызове метода не требуется дополнительного синтаксиса.

7
ответ дан 14 December 2019 в 04:36
поделиться

Я бы справился с этим, добавив метод к интерфейсу HasText для возврата виджета, и реализация просто вернет это.

    public class MyClass extends Widget implements HasText {

            @Override
            public Widget getMyWidget() {
                return this;
            }
    }

Итак, если методу нужен виджет, вы просто вызываете метод getMyWidget () HasText. Он действительно создает некоторый шаблон, но помогает при проверке статического типа.

Если вас не слишком заботит проверка статического типа, вы можете просто иметь контракт (оператор в JavaDoc), что интерфейс HasText предназначен только для реализации в виджетах, а затем просто приводить его, когда вам понадобится Виджет.

Тогда ваш метод будет выглядеть так:

 public void fx(HasText text) //...
1
ответ дан 14 December 2019 в 04:36
поделиться
Другие вопросы по тегам:

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