2013-11-25 4 views
3

Учитывая следующие типы подписей, я могу скомпилировать и запустить код под Maven с помощью JDK 6 и JDK 7, но Eclipse дает «Связанное несоответствие: тип F не является допустимым заместителем для ограниченного параметра <F extends Field<TP,F>> of тип Field<TP,F> "ошибка в TupleVisitor.Eclipse Generics Issue - Обход проблемы?

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

public abstract class Tuple<F extends Field<TP, F>, TP extends Tuple<F, TP>> 

public class VariableTuple<F extends Field<VariableTuple<F>, F>> extends Tuple<F, VariableTuple<F>> 

public class ConstantTuple<F extends Field<ConstantTuple<F>, F>> extends Tuple<F, ConstantTuple<F>> 

public class Field<TP extends Tuple<F, TP>, F extends Field<TP, F>> 

public class ConstantField extends Field<ConstantTuple<ConstantField>, ConstantField> 

public class VariableField extends Field<VariableTuple<VariableField>, VariableField> 

public interface TupleVisitor { 
    public <F extends Field<VariableTuple<F>, F>> void visit(VariableTuple<F> tuple, F field); //Eclipse error 

    public <F extends Field<ConstantTuple<F>, F>> void visit(ConstantTuple<F> tuple, F field); //Eclipse error 
} 

Поданный ошибка по адресу: https://bugs.eclipse.org/bugs/show_bug.cgi?id=422503

Нет простое решение не было выявлено. Хотя ответ Рохита Джаина не будет работать с шаблоном посетителя, я принял его последующий совет и удалил F как параметр типа из поля.

+0

Каков текущий уровень соответствия java-компилятора для проекта? –

+0

Eclipse Уровень соответствия: JavaSE-1.6. –

+0

Источник/целевой уровень Maven - 1.6. –

ответ

2

Это похоже на ошибку с затмением, так как она компилируется под javac для меня тоже. На самом деле, есть несколько ошибок, связанных с самореферентными Java-дженериками, связанными с eclipse, которые я нашел, но этого нет. Так, может быть, вы должны подать один.

Что касается обходного пути этого, я просто нашел тот, который, я сомневаюсь, вам понравится, поскольку вам нужно сделать свой общий интерфейс. Да, вы слышали это правильно. Объявление параметров типа с помощью самого интерфейса делает код компилируемым. Вот код компилирования:

interface TupleVisitor<E extends Field<VariableTuple<E>, E>, 
         F extends Field<ConstantTuple<F>, F>> { 
    void visit(VariableTuple<E> tuple, E field); 
    void visit(ConstantTuple<F> tuple, F field); 
} 

Конечно, есть две переменные типа, как ограничения на обоих из них различны. Проверьте, подходит ли это для вашей потребности, потому что это действительно звучит как странная работа, так как количество параметров типа зависит от общего числа разработчиков класса Tuple (на самом деле странно, не так ли?). Или вы должны сделать некоторые другие изменения.

+0

Мне это нравится. Чтобы позволить шаблону посетителя, ConstantTuple и VariableTuple принимают методы. Я могу просто использовать необработанные типы для методов accept и реализаций посетителя, делая литье вверх по течению. Не самый аккуратный подход, но он снова заставляет меня двигаться. –

+0

Это серьезное предостережение, но если я не получу ответа, который решает эти проблемы, я соглашусь с вами. Спасибо за вашу помощь! –

+0

@AdamAugusta Удаление дженериков и возврат к подходу к кастингам - это не очень хорошо. Тем не менее, если вы можете реорганизовать свои классы, чтобы упростить типичный тип, возможно, вам будет легко. И, конечно же, вы можете принять ответ в любое время. –

0

Проблема заключается в том, что параметры типа предоставляются вызывающим абонентом. Учитывая ваши декларации, кто-то может объявить

class ReallyConstantField extends ConstantField {} 

и затем вызвать TupleVisitor.visit, обеспечивая ReallyConstantField для F. Ограничение типа The visit метода будет читаться

ReallyConstantField extends Field<ConstantTuple<ReallyConstantField>, ReallyConstantField> 

поэтому мы используем ConstantTuple<ReallyConstantField>. Типа ограничение для этого класса будет читаться

ReallyConstantField extends Field<ConstantTuple<ReallyConstantField>, ReallyConstantField> 

, который является неправильным, поскольку ReallyConstantField является ConstantField, который является Field<ConstantTuple<ConstantField>, ConstantField>, которая является необратимым типом.

То есть, хотя вы объявляете параметр типа с привязкой extends, единственным допустимым аргументом типа является один тип.То есть, вам не нужен параметр типа вообще, но может просто объявить:

void visit(ConstantTuple<ConstantField> tuple, ConstantField field); 

Update

BTV, если они должны быть, как пример показывает, параллельные иерархии классов с взаимно однозначным соответствием между классами разных иерархий, существует более простой способ записи дженериков:

abstract class Tuple<F extends Field<TP, F>, TP extends Tuple<F, TP>> {} 

class VariableTuple extends Tuple<VariableField, VariableTuple> {} 

class ConstantTuple extends Tuple<ConstantField, ConstantTuple> {} 

class Field<TP extends Tuple<F, TP>, F extends Field<TP, F>> {} 

class ConstantField extends Field<ConstantTuple, ConstantField> {} 

class VariableField extends Field<VariableTuple, VariableField> {} 

interface TupleVisitor { 
    public void visit(VariableTuple tuple, VariableField field); 

    public void visit(ConstantTuple tuple, ConstantField field); 
} 
Смежные вопросы