2013-10-08 1 views
1

Предположим, я семейного типа, я определил набор методов базового типа:Java дизайн API: Узкий тип возврата методов

interface Foo<T> { 
    Foo<T> a(); 
    Foo<T> b(); 
    ... 
} 

И Bar простирается Foo

interface Bar<T> extends Foo<T> { 
    Bar<T> a(); 
    Bar<T> b(); 
    ... 
} 

А потом Zee простирается Bar

interface Zee<T> extends Bar<T> { 
    Zee<T> a(); 
    Zee<T> b(); 
    ... 
} 

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

class XBar<T> extends XFoo<T> implements Bar<T> { 
    Bar<T> a() { 
     return (Bar<T>)super.a(); 
    } 
    Bar<T> b() { 
     return (Bar<T>)super.b(); 
    } 
    ... 
} 

Это действительно утомительно. Мне интересно, является ли это нормальным явлением в дизайне Java API, или я сделал что-то неправильно, или есть какой-то умный способ обходного метода typecast с одной строкой кода?

Обновления, Чтобы ответить на ваши комментарии и ответ, да, цепочка методов - это одно, чего я хочу достичь здесь. BTW выглядит так: объявление типа BaseStream в Java8 является хорошим примером решения этой проблемы. Я пытаюсь использовать этот подход. Обновит мой прогресс здесь.

Обновления 2, подход BaseStream не работает, когда у меня есть несколько уровней наследования. См. Java inherited Fluent method return type in multiple level hierarchies

+3

Вы не описали 'XFoo ', что не помогает. Было бы хорошо, если бы вы могли продемонстрировать проблему в * полном * способе - вам нужен только один метод, и я подозреваю, что вам тоже не нужно 'Zee'. –

+0

Я предлагаю вам удалить методы из 'Bar ' и 'Zee ' alltogether и позволить им использовать их в 'Foo '. Вы можете, конечно, вернуть «Bar » из метода с возвращаемым типом 'Foo '. Если есть некоторые проблемы с этим, возможно, вам нужно объяснить немного больше того, что должны делать эти интерфейсы и классы. –

+0

Посмотрите мои комментарии ниже, чтобы ответить # 1 –

ответ

2

Почему ваши подклассы должны возвращать тип подкласса?

Liskov Substitution Principle указывает, что объекты могут быть заменены подтипами без изменения каких-либо свойств, поэтому, если вы правильно кодируете свои классы, то вам не требуется бросок, особенно если вы просто возвращаете результат из super.

Единственный раз, когда я могу думать о том, что эта проблема связана с цепочкой методов (например, builder), когда вам нужно получить доступ к дополнительным методам подкласса во время цепочки ... Но это должно быть редко.

+0

По этой логике ковариантные типы возврата бесполезны? –

+0

@MiserableVariable ковариантные типы возврата должны по-прежнему выполнять контракт суперкласса, поэтому они могут быть переданы как их суперкласс типа без проблем. Например, 'Float' по-прежнему является' Number', поэтому, если вам не нужны дополнительные методы в 'Float', вы можете вернуть его как' Number'. – dkatzel

+0

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

 Смежные вопросы

  • Нет связанных вопросов^_^