2016-05-31 3 views
2

Я пытаюсь создать иерархию классов, начиная с абстрактного класса с общим типом. И затем используйте расширенный тип родового во 2-м поколении классов детей. Поскольку я уверен, что не ясно, вот пример:Java generics hierarchy

Идея заключается в том, чтобы иметь таблицу элементов, поэтому в основном:

Simple UML of what I'm trying to do

abstract class AbstractTableOfItems<T> -> Родовой тип таблицы

class Foo -> Один тип элемента

class Bar -> Другой тип по пункту

class SonOfFoo extends Foo

class TableOfFoo extends AbstractTableOfItems<Foo>

class TableOfBar extends AbstractTableOfItems<Bar>

До сих пор так хорошо, все в порядке (не будем заботиться о содержании классов, это не пункт здесь).

Но тогда я хочу таблицу SonOfFoo, и я хочу, чтобы она расширялась TableOfFoo, так как SonOfFoo наследует от Foo. Это не представляется возможным. Возможно, я думаю не так, но я просто не понимаю, почему.

class TableOfSonOfFoo extends TableOfFoo

компилирует, но не так, потому что он все равно будет таблица Foo, общий тип, используемый будучи Foo.

class TableOfSonOfFoo extends TableOfFoo<SonOfFoo>

не компилируется, так как общий тип на AbstractTableOfItems.

Так хорошо я говорю, давайте попробуем переопределить TableOfFoo, чтобы он мог принять наследство:

class TableOfFoo extends AbstractTableOfItems<? extends Foo>

неправильно снова, «супертип не может указать любую подстановку» (я не уверен, что я полностью понимаю вот этот).

Я не могу прикоснуться к AbtractTableOfItems, так как он не будет таким общим, каким я хочу. Поэтому я немного застрял здесь. Я понимаю, что это сработало бы, только имея TableOfSonOfFoo наследовать напрямую от AbstractTableOfItems, но тогда я потеряю все реализации от TableOfFoo.

Я мог бы обойти это, но я пытаюсь думать об иерархии и понимать, почему это не сработает.

ответ

4

будет скомпилирован:

class TableOfFoo<F extends Foo> extends AbstractTableOfItems<F> 

Это говорит: я не люблю выше дизайн. Наличие конкретных типов TableOfFoo и TableOfBar подразумевает, что эти классы, вероятно, делают больше, чем должны. Возможно, вы хотите проверить свой дизайн и посмотреть, можете ли вы упростить ситуацию, используя агрегацию вместо наследования.

+0

Я знаю, но я давал альтернативу этой части его вопроса 'class TableOfFoo extends AbstractTableOfItems '. Я не думаю, что весь вопрос легко подотчетен. –

+0

Спасибо, это похоже на работу. Недостатком является каждый раз, когда я использую тип «F» и класс TableOfFoo, я должен явно передать его Foo, пока он был неявным раньше. Но он действительно работает таким образом. «Возможно, вы хотите проверить свой дизайн и посмотреть, можете ли вы упростить вещи, используя агрегацию вместо наследования». Возможно, действительно, я не настолько уверен в актуальности этого дизайна. – Zazou

+0

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

0

Скорее бы написал это в комментариях, но пока не хватает репутации. Вы пробовали:

class TableOfSonOfFoo extends AbstractTableOfItems<SonOfFoo> 

Это кажется законным для меня и было бы моим первым предположением.

+0

1) Пожалуйста, не пишите вопросы в качестве ответа. Если у вас недостаточно репутации для комментариев, ответьте на них, пока не получите. 2) OP явно объяснил, что он не хочет напрямую расширять 'AbstractTableOfItems'. – Seelenvirtuose

1

Вы можете сделать свой TableOfFoo общий, например.

class TableOfItems<T> extends AbstractTableOfItems<T> 

и вытащить все функциональные возможности, которые вы хотите поделиться с этим. Затем создайте подклассы этого:

class TableOfFoo extends TableOfItems<Foo> 
class TableOfSonOfFoo extends TableOfItems<SonOfFoo> 

Имейте в виду, что AbstractTableOfItems<Foo> не супертипом AbstractTableOfItems<SonOfFoo>, так TableOfFoo и TableOfSonOfFoo на самом деле братья в иерархии.

+0

Спасибо за ответ, но при этом TableOfItems будет таблицей общих элементов «T», а не таблицей Foo, что означает, что я не могу использовать Foo в качестве моего общего типа в методах этого класса. Это была именно точка этой иерархии. – Zazou

+0

@Zazou поэтому добавьте привязку к переменной типа: 'T extends Foo'. –

+0

Но тогда это был бы TableOfFoo, и TableOfItems не понадобились бы, и это было бы ответом от Шона Патрика Флойда, прямо выше;) – Zazou