Почему методы возвращают self по умолчанию в Smalltalk?

Задний план

В Smalltalk, если вы явно ничего не возвращаете, то передача сообщения оценивается получателю (или «я» в контексте сообщения).

Например, с учетом этого метода:

MyClass >> myMethod
  Transcript show: 'hello'; cr.

Оценка (не "распечатывать") это:

| myInstance |
myInstance := MyClass new.
myInstance myMethod.

Если ‹print-it› выполняется для последнего вызова, результатом будет сам экземпляр.

Вопросы

  • Почему это было разработано таким образом?
  • Какая идея стоит за этим?
  • Какова была философская подоплека?
  • Какая практическая польза от этого? Это для облегчения цепочки методов?

person Sebastian N.    schedule 27.12.2012    source источник
comment
Интересное замечание по теме: блоки возвращают результат последнего выражения.   -  person Lukas Renggli    schedule 27.12.2012


Ответы (5)


Одна очень простая причина еще не указана: в виртуальной машине возврат self проще и эффективнее, чем возврат любого другого объекта.

Байт-коды Smalltalk реализуют стековую машину. Это означает, что аргументы передаются путем помещения их в стек, а не в регистры. В дополнение к аргументам, перечисленным в сигнатуре метода, всегда передается скрытый аргумент, который является получателем сообщения. Таким образом, даже для унарных методов (без аргументов) получатель помещается в стек, затем метод выполняется, а значение получателя в стеке — это то, как метод узнает «я». Возвращая «я», если не указан явный оператор возврата, виртуальная машина может просто оставить цикл «я» в стеке, что экономит по крайней мере одну операцию сохранения памяти. Таким образом, с точки зрения эффективности и простоты возврат "self" является наиболее элегантным решением.

person Vanessa Freudenberg    schedule 30.12.2012
comment
Я подозреваю, что ты попал в точку. Это похоже на те оптимизации, которые вы найдете в оригинальной реализации Smalltalk-80. - person akuhn; 03.01.2013

Синяя книга Smalltalk-80 (Язык и его реализация) ничего не говорит о том, почему по умолчанию возвращается приемник.

Однако на странице 27 (раздел «Возврат значений») есть цитата, которая может вам помочь:

«Даже если отправителю не нужно передавать информацию, получатель всегда возвращает значение для выражения сообщения. Возвращаемое значение указывает на то, что ответ на сообщение завершен. (...)»

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

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

person Esteban A. Maringolo    schedule 27.12.2012

Я не создатель smalltalk, но, кажется, это лучший способ сделать.

Например, если вы выполните:

var := myInstance myMethod.

тогда вопрос: кем вы хотите, чтобы var стал? Одним из вариантов будет nil. Но это немного сбивает с толку, потому что вы работаете с определенными объектами, а nil на самом деле не определено. Таким образом, вы можете рассматривать это так, как будто вы назначаете myInstance var и просто вызываете myMethod по пути. Также это, вероятно, можно рассматривать как сокращение для

 var := myInstance myMethod; yourself.

Если смотреть изнутри, то из всех данных, доступных самому объекту, наверное, самое подходящее - тоже self. Еще раз повторю, что nil можно вернуть, но свое мнение по этому поводу я уже высказывал.

В Smalltalk нет такого понятия, как метод void, который ничего не возвращает, и нет проверки типов. Так что метод просто должен что-то возвращать. Как будто Объект говорит:

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

Лично я думаю, что возвращение nil тоже может быть хорошим решением, и приложения Objective-C очень часто используют материал nil, но Smalltalk устроен таким образом, и я думаю, что это неплохое решение.

person Uko    schedule 27.12.2012

Методы возвращают self по умолчанию по нескольким причинам.

  1. Методы Smalltalk должны что-то возвращать
  2. self — самый простой объект для возврата
  3. self — самый быстрый возвращаемый объект
  4. Возвращение себя позволяет естественным образом работать нескольким шаблонам проектирования.

Позвольте мне объяснить # 4 немного больше. Одним из распространенных шаблонов для инициализации объекта является определение метода new для класса, который выглядит следующим образом:

new
   ^super new initialize

Этот шаблон зависит от инициализации, возвращающей self. Однако добавление ^self в конце метода initialize является ненормальным. В этом нет необходимости, потому что метод все равно вернет себя.

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

person David Buck    schedule 05.01.2013
comment
Да, возврат self помогает связывать сообщения. Эту идею можно найти и в (некоторых) методах Java. - person U. Windl; 27.05.2021

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

Поэтому я был счастлив найти возвращаемое значение для каждого вызова метода или отправки сообщения в Smalltalk. Если вы решите, чтобы каждый метод возвращал какое-то значение, вы собираетесь спросить, каким может быть ваше значение по умолчанию. Сам объект (self) — это очень естественный способ использования в качестве значения по умолчанию. Или спросить наоборот: что может быть лучшим возвращаемым значением?

person pintman    schedule 27.12.2012