Smalltalk в примерах/Сообщения: различия между версиями

Содержимое удалено Содержимое добавлено
Строка 117:
(Обычно используемое обозначение указания имени метода стороны экземпляра: <tt>ClassName>>methodName</tt>. Для методов стороны класса: <tt>isClassName class>>methodName</tt>.)
 
<!--
The receiver of the message
All messages have to be sent to an object — there's no such thing as a message in isolation. If you create an object in a method, it's easy to send a message to the object. For example:
 
MyClass>>doThis
array := Array new: 3.
array at: 1 put: 2.
(The generally used notation to show instance side method names is ClassName>>methodName. For classside methods, the notation isClassName class>>methodName.)
-->
 
===Self===
Строка 138 ⟶ 128 :
Если метод нуждается в другом методе для выполнения некоторой работы, пошлите сообщения <i>self</i>. Фактически, если вы не знаете, какому объекту послать сообщение, хорошим правилом будет послать его <i>self</i>.
 
<!--
Smalltalk methods average about seven lines, so for an object to do any serious work there's a good chance that you will have split the work into several methods (assuming you want to have short methods). How does a method invoke another method defined on the same object? Answer: the object sends a message to itself. Smalltalk has a special variable for just such use — self — which always refers to the object that is executing the code — the message receiver. Note that self refers to the receiver even if the the code was defined on a superclass of the receiver's class.
 
MyClass>>processObject: anObject
self doThisWithObject: anObject.
self doThatToObject: anObject.
 
===Super===
If a method needs to call on a support method to do some work, send the message to self. In fact, a good rule of thumb is, if you can't figure out what object to send the message to, send it to self.
-->
 
Если вы помните как ищется сообщение, Smalltalk сначала ищет метод в объекте которому пришло сообщение. Если здесь сообщение не найдено, он затем ищет его в суперкласс и т.д. Но что мы должны делать если хотим сразу начать искать сообщение в суперклассе? Smalltalk предоставляет другую специальную переменную, <i>super</i>. Таким образом, если вы хотите начать с суперкласса, пошлите сообщение <i>super</i>.
===супер===
 
Когда <i>super</i> должна использоваться? Один из основных примеров это создание экземпляра. Если вы хотите инициализировать переменные экземпляра вы обычно пишете метод <tt>initialize method</tt> на стороне экземпляра. Вы не можете наследовать метод <tt>new</tt> пока у вас нет метода <tt>initialize</tt>, но вы должны написать свой собственный метод <tt>new</tt>, который будет наследовать поведение метода <tt>new</tt> от суперкласса. Знак <tt>^</tt>, показанный ниже, означает <i>возвращаемое</i> значение.
Если вы помните как ищется сообщение, Smalltalk сначала ищет метод в объекте которому пришло сообщение. Если здесь сообщение не найдено, он затем ищет его в суперкласс и т.д. Но что мы должны делать если хотим сразу начать искать сообщение в суперклассе? Smalltalk предоставляет другую специальную переменную, <i>супер</i>. Таким образом, если вы хотите начать с суперкласса, пошлите сообщение <i>супер</i>.
 
MyClass>>initialize
Когда <i>супер</i> должна использоваться? Один из основных примеров это создание экземпляра. Если вы хотите инициализировать переменные экземпляра вы обычно пишете метод <tt>инициализировать</tt> на стороне экземпляра. Вы не можете наследовать метод <tt>новый</tt> пока у вас нет метода <tt>инициализация</tt>, но вы должны написать свой собственный метод <tt>новый</tt>, который будет наследовать поведение метода <tt>новый</tt> от суперкласса. Знак <tt>^</tt>, показанный ниже, означает <i>возвращаемое</i> значение.
set some variables
 
MyClass class>>new
МойКласс>>инициализацыя
^super new initialize
... присвоение некоторых переменных ...
 
класс МойКласс>>новый
^супер новый инициализацыя
 
Фактически, <i>супер не</i> ссылается на суперкласс объекта которому пришло сообщение. Вместо этого, он ссылается на суперкласс объекта в котором определён выполняемый код. Это тонкое различие, но очень важное, потому что если бы это было не так, было бы легко получить бесконечную рекурсию. Давайте посмотрим почему. Пусть мы имеем иерархию классов КлассДва подкласс КлассаОдин, и КлассТри подкласс КлассаДва, как показано на Рисунке~\ref{ierarhix123}.
 
\begin{figure}[!htb]
\begin{center}
\includegraphics{ierarhix123.eps}
\end{center}
\caption{Иерархия наследования КлассаОдин, КлассаДва и КлассаТри}
\label{ierarhix123}
\end{figure}
 
Фактически, <i>super</i> не ссылается на суперкласс объекта которому пришло сообщение. Вместо этого, он ссылается на суперкласс объекта в котором определён выполняемый код. Это тонкое различие, но очень важное, потому что если бы это было не так, было бы легко получить бесконечную рекурсию. Давайте посмотрим почему. Пусть мы имеем иерархию классов ClassTwo подкласс ClassOne, и ClassThree подкласс ClassTwo.
Все три класса имеют переменные экземпляра, которые должны быть инициализированы, и код, делающий это, выглядит примерно как следующий.
 
ClassOne>>initialize
КлассОдин>>инициализация
set some variables
... присвоение некоторым переменным ...
ClassTwo>>initialize
super initialize.
set some variables
ClassThree>>initialize
super initialize.
set some variables
 
Когда мы создаём экземпляр ClassThree и выполняем код инициализация ClassTwo из объекта ClassThree, на что ссылается <i>super</i>? Если он ссылается на суперкласс класса <i>выполняющего</i> код, тогда суперклассом должен быть ClassTwo, и сообщение <tt>initialize</tt> должно быть снова послано ClassTwo. Т.е., мы попали в бесконечный цикл. С другой стороны, если супер ссылается на суперкласс класса, в котором определён код, сообщение должно быть послано ClassOne и бесконечного цикла не возникает.
КлассДва>>инициализация
супер инициализация
... присвоение некоторым переменным ...
 
Ключевым моментом, который надо отметить, является то что <i>self</i> идентифицирует себя самого и может быть просмотрен, так же как переменная, и быть параметром. Однако, <i>super</i> - это не идентификатор и вы не можете просмотреть его и использовать в качестве параметра. Когда вы выполняете метод, компилятор переводит текст в байткод. Когда он встречает слово <i>супер</i>, он создаёт код который заставляет среду выполнения искать метод в суперклассе класса, определившего метод. Поэтому <i>super</i> - это просто механизм для сообщения компилятору как создавать байткод.
КлассТри>>инициализация
супер инициализация
... присвоение некоторым переменным ...
 
Когда мы создаём экземпляр КлассаТри и выполняем код инициализация КлассаДва из объекта КлассаТри, на что ссылается <i>супер</i>? Если он ссылается на суперкласс класса <i>выполняющего</i> код, тогда суперклассом должен быть КлассДва, и сообщение <tt>инициализация</tt> должно быть снова послано КлассуДва. Т.е., мы попали в бесконечный цикл. С другой стороны, если супер ссылается на суперкласс класса, в котором определён код, сообщение должно быть послано КлассуОдин и бесконечного цикла не возникает.
 
Ключевым моментом, который надо отметить, является то что <i>сам</i> идентифицирует себя самого и может быть просмотрен, так же как переменная, и быть параметром. Однако, <i>супер</i> - это не идентификатор и вы не можете просмотреть его и использовать в качестве параметра. Когда вы выполняете метод, компилятор переводит текст в байткод. Когда он встречает слово <i>супер</i>, он создаёт код который заставляет среду выполнения искать метод в суперклассе класса, определившего метод. Поэтому <i>супер</i> - это просто механизм для сообщения компилятору как создавать байткод.
 
<!--
super
If you remember how message lookup works, Smalltalk looks for the method first in the object that is
receiving the message. If it can't find a method there, it next looks in the superclass, etc. But what do we do if we
explicitly want to start looking in our superclass? Smalltalk provides another special variable, super. So, if you
want to start at your superclass, send a message to super.
When would this be useful? One common example is during instance creation. If you want to initialize some
instance variables you usually write an initialize method on the instance side. You can no longer inherit
new since it doesn't send initialize, so you have to write your own new method, which will inherit the
behavior of new from a superclass. Note that the caret (^) shown below means return.
MyClass>>initialize
... set some variables ...
MyClass class>>new
^super new initialize
In fact, super does not refer the the superclass of the object that received the message. Instead, it refersto the
superclass of the object that defined the code being executed. It's a subtle difference but an important one
because if it were not this way it would be easy to end up in infinite recursion. Let's look at why. Let's say we
have a class hierarchy with ClassTwo subclassed off ClassOne, and ClassThree subclassed off ClassTwo as
shown in Figure 2-2.
All three classes have instance variables that must be initialized and the initialization code looks like the
following.
ClassOne>>initialize
... set some variables ...
ClassTwo>>initialize
super initialize.
... set some variables ...
ClassThree>>initialize
super initialize.
... set some variables ...
When we create an instance of ClassThree and execute the ClassTwo initialize code from the ClassThree
object, what does super refer to? If it refers to the superclass of the class executing the code, then super will be
ClassTwo and the initialize message will be again sent to ClassTwo. Ie, we'll end up in an infinite loop. On
the other hand, if super refers to the superclass of the class defining the code, the message will be sent to
ClassOne and everything works fine.
A key point to note is that self has an identity of its own and can be inspected, assigned to a variable, and
passed as a parameter. However, super has no identity and you cannot inspect it or assign it. When you accept a
method, the compiler compiles the method text into byte codes. When it comes across the word super it
generates byte codes that instruct the run-time engine to start the method lookup in the superclass of the class
defining the method. Thus super is simply a mechanism for telling the compiler how to generate byte codes.
-->
 
[[Smalltalk в примерах/Методы|Методы →]]