Generi c приведение / проверка экземпляра / исключение параметра типа - PullRequest
0 голосов
/ 18 февраля 2020

Проблема.

A Detect может предоставить специфицированный c тип из Detectables, который выглядит как

interface
Detectable
{/*...*/}

interface
Some_detectable
implements Detectable
{/*...*/}

A supply метод в Detect должен иметь возможность принимать любой Detectable и предоставлять его, только если он имеет специфицированный c тип . Я представляю описанную ситуацию следующим образом

abstract class
Detect<D extends Detectable>
{
  private final Set<D>
  DETECT=new LinkedHashSet<>();

  void
  supplying(Detectable d)
  {
    /*[ DETECT.add(d); ]*/
    /*supply d if of type D*/
  }
}

Attemps.

Сначала я попытался создать метод для приема D, а другой метод обрабатывает случай, когда аргумент не является D но только любые Detectable.

К сожалению, я не могу исключить D из второго метода или типа класса D.

Следовательно, эти методы могут привести к неоднозначности метод (если D является необработанным Detectable)

abstract class
Detect<D extends Detectable>
{
  /*...*/
  void
  supplying(D d)
  {
    DETECT.add(d);
  }
  void
  supplying(Detectable d){}
}

Мой текущий рабочий , но некрасивый попытка решить проблему.

abstract class
Detect<D extends Detectable>
{
  final Set<D>
  DETECT=new LinkedHashSet<>();

  void
  supplying(Detectable d)
  {
    D
    casted= try_cast(d);

    if(casted==null) {return;}
    DETECT.add(casted);
  }

  abstract protected D
  try_cast(Detectable detectable);
}

class
Some_detect
extends Detect<Some_detectable>
{
  @Override protected Some_detectable
  try_cast(Detectable d)
  {
    return d instanceof Some_detectable
           ? (Some_detectable)d
           : null;
  }
}

1 Ответ

1 голос
/ 19 февраля 2020

Я предлагаю вам сохранить объект класса Class<D> и использовать его для проверки класса d. Java Обобщения стираются во время выполнения, поэтому вы не можете написать что-то вроде d instanceof D без сохранения этого класса.

Вот пример кода (извините, я отредактировал ваш код, чтобы он соответствовал Java стилю кода) :

interface Detectable {}
interface SomeDetectable extends Detectable {}

abstract class Detect<D extends Detectable> {
    private final Class<D> dClass;
    private final Set<D> detect = new LinkedHashSet<>();

    protected Detect(Class<D> dClass) {
        this.dClass = dClass;
    }

    void supplying(Detectable d) {
        if (dClass.isInstance(d)) {
            detect.add(dClass.cast(d));
        }
    }
}

class SomeDetect extends Detect<SomeDetectable> {
    SomeDetect() {
        super(SomeDetectable.class);
    }
}

Вы можете упростить использование базового класса Detect<D>, автоматически обнаружив параметр типа в данном конкретном случае, поскольку он фактически хранится в метаданных класса. Но это подход fr agile, и я обычно его не рекомендую.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...