2009-02-12 2 views
1

Учитывая набор классов кортежей в языке ООП: пара, тройной и квадратный, должна быть тройная подкласса пара и квад-подкласс Triple?Должны ли кортежи подкласса друг другу?

Проблема, как я вижу, заключается в том, что тройка должна быть заменяемой как пара, а также Quad для Triple или Pair. Тройной также Пара и Квадрат также a Triple и пара.

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

С другой стороны, должны ли они быть отдельными типами? Я вижу преимущество в более сильной проверке типов - там, где вы не можете передать тройку методу, который ожидает пару.

Я склоняюсь к использованию наследования, но буду очень благодарен за вклад от других?

PS: В случае, если это имеет значение, классы будут (конечно) носить общий характер.

PPS: На пути более субъективная сторона, должны ли имена быть Tuple2, Tuple3 и Tuple4?


Редактировать: Я думаю об этом больше как о слабосвязанных группах; не специально для таких вещей, как координаты x/y x/y/z, хотя они могут быть использованы для таких целей. Это было бы похоже на то, что нужно общее решение для множественных возвращаемых значений из метода, но в форме с очень простой семантикой.

Тем не менее, меня интересуют все способы, которыми другие на самом деле использовали кортежи.

ответ

1

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

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

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

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

Редактировать: Если вы хотите получить общую информацию, попробуйте просмотреть немного Haskell или ML-семейства (OCaml/F #), чтобы увидеть, как они используются, а затем сформировать собственные решения.

+0

Можете ли вы улучшить свой ответ с помощью (быстрого/простого) примера, когда перегрузка не выполняется? –

+0

BTW, он играл с Haskell, что я впервые познакомился с концепцией кортежей. :) –

0

Я бы пошел с 0,1,2 или бесконечность. например null, 1 объект, ваш класс Pair или некоторая коллекция.

Ваша пара может даже реализовать интерфейс Collection.

Если существует определенная связь между тремя или четырьмя элементами, ее, вероятно, следует назвать.

[Возможно, я пропускаю эту проблему, но я просто не могу думать о случае, когда я хочу, чтобы конкретно связать 3 вещи в общем виде]

+0

Мне нравится идея быть коллекцией; вероятно, List. Не карта, потому что пара не предназначена для эквивалента Map.Entry. –

1

Мне кажется, что вы должны сделать общий Интерфейс Tuple (или используйте что-то вроде сборника, упомянутого выше), и у вас есть пара и классы из 3-кортежей, реализующие этот интерфейс. Таким образом, вы можете воспользоваться полиморфизмом, но также позволить паре использовать более простую реализацию, чем кортеж произвольного размера. Вероятно, вы хотите, чтобы ваш интерфейс Tuple включал в себя .x и .y-аксессоры как стенографию для первых двух элементов, а более крупные кортежи могли реализовать свои собственные сокращения, подходящие для предметов с более высокими индексами.

1

зависит от семантики, что вам нужно -

  • пар противоположностей семантический не совместим с 3-кортежем подобных объектов
  • пара координат в полярном пространстве семантический не совместим с 3-кортеж координат в евклидовом пространстве

если ваша семантика простые композиции, то общий класс кортеж <N> бы больше смысла

1

Как и большинство вопросов, связанных с дизайном, ответ - это зависит.

Если вы ищете обычный дизайн Tuple, Tuple2, Tuple3 и т. Д. Это путь. Проблема с наследованием заключается в том, что, прежде всего, Триплет - это не тип пары. Как бы вы применили метод equals для него? Является ли тройка равной паре с первыми двумя пунктами одинаковыми? Если у вас есть коллекция пар, можете ли вы добавить к ней триплет или наоборот? Если в вашем домене это нормально, вы можете пойти с наследованием.

В любом случае, он платит за наличие интерфейса/абстрактного класса (возможно, Tuple), который все это реализует.

+0

@ amit.dev: Какие методы будет объявлен интерфейсом Tuple? –

+0

@ amit.dev: Я бы подумал, что Triple не является «equals()» парами, потому что Pair.getClass()! = Triple.getClass() - позволяя somePair.equals (someTriple) нарушать равный контракт, потому что someTriple .equals (somePair) обязательно должны быть ложными. –

+0

@ amit.dev: Но поскольку somePair не равен someTriple, это не означает, что someTriple не является экземпляром пары. –

0

Gilad Bracha blogged about tuples, который я нашел интересное чтение.

Один момент он сделал (правильно ли или нет я еще не могу судить) был:

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

{S. T. U. V} < = {S. T. U} < = {S. Т} < = {S}

[и] читать только кортежи ковариантны:

< Т1 = Т2, S1, S2, < = ==> {S1. T1} < = {S2.T2}

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

+0

Да неизменность хорошая. Но я не вижу причин для подтипирования, поэтому Triple наследует от пары. – MichaelGG

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