Почему to_a и to_ary ведут себя по-разному в подклассах Array?

Если у вас есть подкласс X массива, то выполнение X#to_a возвращает объект массива, а выполнение X#to_ary возвращает объект x.

Хотя я понимаю, что to_a означает "я могу быть преобразован в массив", а to_ary означает "я веду себя как массив", я не понимаю, почему первый реализует изменение класса, а второй - нет.

Кроме того, не является ли возвращение подкласса Array достаточным для to_a в соответствии с принципом подстановки Лискова?


person Andrew Grimm    schedule 17.04.2012    source источник
comment
Что бы это ни стоило, я тоже думаю, что это глупо, что вызов to_a для подкласса массива изменит класс на массив, когда он уже является массивом (is_a?(Array) вернет true)   -  person Tyler Rick    schedule 28.03.2014


Ответы (2)


Достаточно ли «потому что так это определено»?

to_a

Возвращает self. Если вызывается в подклассе Array, преобразует приемник в объект Array.

to_ary

Возвращает self.

Вероятно, нет, так что здесь мы идем в кроличью нору.

Помимо того факта, что документация окончательно утверждает, что это именно так, за рассуждения, возможно, действительно отвечает только Матц и др.

Если покопаться, может показаться, что to_ary используется, когда происходят неявные преобразования типов. Его использование для неявных преобразований, похоже, также отражено в этом запросе функции. Другими словами, если объект отвечает на to_ary, то его следует рассматривать как Array, и таким образом он используется внутри. Таким образом, to_a будет, когда вы (явно) хотите Array, а не какой-то подкласс.

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

person Andrew Marshall    schedule 17.04.2012

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

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

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

person DigitalRoss    schedule 17.04.2012