Java - Переопределение типа возвращаемого значения расширенного интерфейса, когда тип возвращаемого значения использует универсальные шаблоны для параметра собственного метода типы

я наткнулся на любопытство наследования java, и я хотел бы, чтобы вы спросили лучшие идеи по этому поводу:

Предположим, два интерфейса A и A1

Интерфейс A1 расширяет A

Интерфейс A имеет метод, который возвращает универсальный тип.

Универсальный тип будет иметь вид GenericType .

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

Основная идея теперь состоит в том, чтобы изменить этот общий тип возвращаемого значения с GenericType в интерфейсе A в GenericType в интерфейсе A1

Что ж, поначалу кажется, что это просто (плохие вещи появятся позже)

Мы объявляем интерфейс A как

public interface InterfaceA {
  public GenericType<? extends Object> getAGenericType();  
}

и интерфейс A1 как

public interface InterfaceA1 extends InterfaceA
{
  @Override
  public GenericType<String> getAGenericType();
}

как видите ли, мы вынуждены писать GenericType в самом интерфейсе A, чтобы можно было заменить его универсальными «подклассами». (Фактически, общий параметр универсального типа является подклассом, а не сам универсальный тип)

Теперь предположим, что GenericType имеет свой собственный метод, похожий на:

public interface GenericType<D>
{
  public void doSomethingWith( D something );
}

Теперь попытка создать экземпляр A1 отлично работает.

Скорее попытка создать экземпляр A будет отстой. Чтобы понять, почему посмотрите на этот класс «использовать интерфейс»:

public class LookAtTheInstance
{
  @SuppressWarnings("null")
  public static void method()
  {
    InterfaceA a = null;
    InterfaceA1 a1 = null;

    GenericType<String> aGenericType = a1.getAGenericType();

    GenericType<? extends Object> aGenericType2 = a.getAGenericType();
    Object something = null;
    aGenericType2.doSomethingWith( something );
  }
}

Вы спросите: «А теперь?»

Он не работает на последних строках. Фактически параметр «что-то» даже не из типа «Object», а из типа «? Extends Object». Таким образом, вы не можете передать объявленный тип «Объект». Вы вообще ничего не можете передать.

В итоге вы объявляете хорошие интерфейсы, которые, как оказалось, нельзя создать правильно.

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

Или как бы вы обошли такой модельный случай?

Или мне просто не хватает простого пункта в универсальном объявлении, и мой пример возможен таким образом?

- --------- (1) редактировать из-за ответов -----------

Очень хорошая основная идея - сделать интерфейс более абстрактным! Сначала у меня возникла точно такая же идея, но ... (это должно произойти)

Предположим, что делаю следующее:

Мы представляем новый интерфейс AGeneric

public interface InterfaceAGeneric<T>{
  public GenericType<T> getAGenericType();
}

Теперь нам нужно расширить A и A1 из этого нового интерфейса :

public interface InterfaceA extends InterfaceAGeneric<Object>{}
public interface InterfaceA1 extends InterfaceAGeneric<String>{}

Это работает нормально, хотя и прерывает путь исходного наследования.

Если мы хотим, чтобы A1 по-прежнему можно было расширить от A, мы должны изменить A1 на

public interface InterfaceA1 extends InterfaceA, InterfaceAGeneric<String>{}

, и снова возникает проблема. Это не работает, поскольку мы косвенно расширяем один и тот же интерфейс разными универсальными типами. К сожалению, это запрещено.

Вы видите проблему?

-

И чтобы указать на другое обстоятельство:

Если вы примените GenericType до GenericType , это очевидно работает. Пример:

public class LookAtTheInstance
{
  public static void main( String[] args )
  {
    InterfaceA a = new InterfaceA()
    {
      @Override
      public GenericType<? extends Object> getAGenericType()
      {
        return new GenericType<Object>()
        {
          @Override
          public void doSomethingWith( Object something )
          {
            System.out.println( something );
          }
        };
      }
    };
    ;

    @SuppressWarnings("unchecked")
    GenericType<Object> aGenericType2 = (GenericType<Object>) a.getAGenericType();

    Object something = "test";
    aGenericType2.doSomethingWith( something );
  }  
}

Мне кажется, что определение типа параметра метода

public interface GenericType<D extends Object>
{
  public void doSomethingWith( D something );
}

неверно.

Если D объединяется с «? Extends Object», почему тип параметра не должен быть «Object» "?

Разве это не поможет?

13
задан Omnaest 20 February 2011 в 15:08
поделиться