Должны ли кортежи подклассифицировать друг друга?

StackOverflow https://stackoverflow.com/questions/539833

Вопрос

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

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

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

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

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

ПС:Если это имеет значение, классы (конечно) будут универсальными.

ППС:Если говорить более субъективно, следует ли называть имена Tuple2, Tuple3 и Tuple4?


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

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

Это было полезно?

Решение

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

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

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

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

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

Другие советы

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

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

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

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

это зависит от семантики, которая вам нужна -

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

если ваша семантика представляет собой простые композиции, тогда более разумным будет универсальный класс Tuple<N>.

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

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

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

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

Гилад Браха вел блог о кортежах, что мне показалось интересным чтением.

Он высказал одно замечание (правильно или нет, я пока не могу судить):

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

{С.Т.У.V } <= {С.Т.У} <= {С.Т} <= {S}

[и] кортежи только для чтения являются ковариантными:

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top