Почему методы возвращают "self" по умолчанию в Smalltalk?
Фон
В Smalltalk, если вы ничего явно не возвращаете, то передача сообщения оценивается получателю (или "себе" в контексте сообщения).
Например, учитывая этот метод:
MyClass >> myMethod
Transcript show: 'hello'; cr.
Оценивая (doint "print-it") это:
| myInstance |
myInstance := MyClass new.
myInstance myMethod.
Если
Вопросы
- Почему это было разработано таким образом?
- Какая идея стоит за этим?
- Каков был философский фон?
- Каковы практические выгоды от этого? Это для облегчения цепочки методов?
5 ответов
Одна очень простая причина еще не указана: в Виртуальной машине возвращать себя проще и эффективнее, чем возвращать любой другой объект.
Байт-коды Smalltalk реализуют стековую машину. Это означает, что аргументы передаются путем помещения их в стек, а не в регистры. В дополнение к аргументам, перечисленным в сигнатуре метода, всегда передается скрытый аргумент, который является получателем сообщения. Таким образом, даже для унарных методов (без аргументов) получатель помещается в стек, затем метод выполняется, и значение получателя в стеке определяет, как метод знает "себя". Возвращая "self", если явного оператора return не задано, виртуальная машина может просто оставить "self" в стеке, что сохраняет как минимум одну операцию сохранения памяти. Таким образом, с точки зрения эффективности и простоты, возвращение "я" - самая элегантная вещь.
Синяя книга Smalltalk-80 ("Язык и его реализация") ничего не говорит о том, почему он возвращает получателя по умолчанию.
Однако на странице 27 есть цитата (раздел "Возвращение значений"), которая может вам помочь:
"Даже если никакая информация не должна быть передана обратно отправителю, получатель всегда возвращает значение для выражения сообщения. Возвращаемое значение указывает, что ответ на сообщение завершен. (...)"
Имейте в виду, что в Smalltalk методы активируются посредством отправки сообщений, поэтому для сообщения существует полный круговой обход (который может заканчиваться исключением MessageNotUnderstood). Концепция отправки сообщений имеет первостепенное значение.
В зависимости от цели сообщения есть несколько примеров хорошей практики для возвращения, но это тема другой истории.
Я не создатель болтовни, но, похоже, это лучшее, что можно сделать.
Например, если вы выполните:
var := myInstance myMethod.
тогда вопрос: что ты хочешь var
становиться? Один вариант будет nil
, Но это немного сбивает с толку, потому что вы работаете с определенными объектами и nil
на самом деле неопределенный. Таким образом, вы можете относиться к этому, как вы назначаете myInstance
в var
и просто вызываю myMethod по пути. Также это можно рассматривать как сокращение для
var := myInstance myMethod; yourself.
Если вы посмотрите изнутри, то из всех данных, доступных самому объекту, наиболее подходящая вещь, вероятно, также self
, Еще раз, nil
можно вернуть, но я уже высказал свое мнение по этому поводу.
В Smalltalk нет такой вещи, как метод void, который ничего не возвращает, и нет проверки типов. Так что метод просто должен что-то вернуть. Это как объект говорит:
Я могу вернуть себя для любого вызова метода по умолчанию, потому что я всегда знаю о себе, и вы можете переопределить это поведение в случае, если вы хотите, чтобы я возвратил что-то еще.
Лично я думаю, что возвращение nil
может быть хорошо, и приложения Objective-C используют nil
очень часто, но Smalltalk сделан таким образом, и я думаю, что это довольно хорошее решение.
Методы возвращают себя по умолчанию по нескольким причинам.
- Методы Smalltalk должны возвращать что-то
- Самость - это самый легкий объект для возвращения
- Самость - самый быстрый объект для возвращения
- Возврат себя позволяет нескольким шаблонам дизайна работать естественно
Позвольте мне объяснить #4 немного больше. Один общий шаблон для инициализации объекта - это определение нового метода для класса, который выглядит следующим образом:
new
^super new initialize
Этот шаблон зависит от инициализации, возвращающей себя. Однако ненормально добавлять ^ self в конце метода инициализации. Это не нужно, потому что метод все равно вернет себя.
В конце концов, возвращение себя - это просто естественный выбор по умолчанию, учитывая, что вы должны что-то вернуть.
Исходя из Java, вы знаете об исключениях NullPointException при работе с неопределенными возвращаемыми значениями. Кроме того, ваш код должен выполнять условную проверку на ноль здесь и там.
Поэтому я был рад найти возвращаемое значение для каждого вызова метода или сообщения, отправленного в Smalltalk. Если вы решите, чтобы каждый метод возвращал какое-то значение, вы спросите, каким может быть ваше значение по умолчанию. Сам объект (self) является очень естественным способом использования в качестве значения по умолчанию. Или спросить наоборот: что может быть лучшим возвращаемым значением?