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

Содержимое удалено Содержимое добавлено
м Категоризация по запросу на w:ВП:РДБ
Нет описания правки
Строка 1:
Сейчас мы рассмотрим более подробно как создавать экзэмплярыэкземпляры класса. Основное сообщение для создания экзэмпляраэкземпляра это \emph{новый}, которое возвращает новый экзэмплярэкземпляр класса. Например,
 
<!--
Строка 8:
совокупность := УпорядоченнаяСовокупность новый.
 
Если ты пошлёшпошлёшь классу совокупность сообщение \emph{новый}, оно вернёт новую совокупность\footnote{Sending new: to a class that is not variable sized will generate an exception}. Размер всегда должен быть нулевым пока совокупность пустая, но вместимость будет равна вместимости по умолчанию для данного класса. Вместимость это количество элементов которые ты можэшможешь поместить в совокупность до того как он начнёт увеличиваться. Например, выполнение следующих выражений даёт вместимость показаную справа.
 
<!--
Строка 18:
\end{verbatim}
 
Увеличение вместимости совокупности довольно дорого потому что увеличивающий код создаёт новую совокупность с большэйбольшей вместимостью, копирует все элементы текущей совокупности, затем большая совокупность становится новой. Если ты знаеш насколько большой должна быть совокупность, или представляеш начальную вместимость, более эффективно создать совокупность при помощи сообщения \verb|new:| где параметр это начальная вместимость. Некоторые совокупности, такие как Массив, не увеличиваются автоматически, поэтому важно определять их вместимость (для совокупностей которые на увеличиваются автоматически, размер и вместимость это одно и то жэже). Например,
 
<!--
Строка 28:
поток := (Поток новый: 100) writeStream.
 
Методы \verb|новый| и \verb|новый:| реализованы в \verb|Behavior|, однако они переопределены во многих классах. Из за того что твой класс наследует \verb|новый| и \verb|новый:|, ты не должен переопределять их пока твой класс ---. Есть два типа присвоения которые могут быть сделаны: присваивание переменной начального значения по умолчанию, и присваивание переменной значения спецыфичногоспецифичного для экэмпляра. Давай рассмотрим каждый вариант.
 
<!--
Строка 37:
==Присваивание значений по умолчанию==
 
Допустим у нас есть объект \emph{Сотрудник} который следит за дозволенным и реальным количеством часов простоя и времени болезни. Когда экзэмплярэкземпляр \verb|Сотрудника| создаётся, мы хотим иницыализироватьинициализировать его переменные экзэмпляраэкземпляра подходящими значениями, не обращая внимания на имя или жалование сотрудника. Есть два способа сделать это. Ты можэшможешь использовать lazy иницыализацыюинициализацию как мы делали в Главе 4, Переменные. Например,
 
<!--
Строка 48:
лож: [sickHoursUsed]
 
В качестве альтернативы, ты можешможешь иницыализироватьинициализировать все данные в одном методи \verb|иницыализацыяинициализация|. Lazy иницыализацыяинициализация полезна ести твой объект никогда не использует данные которые сложны для иницыализацыиинициализации, но на доступ к данным тратится дополнительное сообщение при каждом обращении. Если ты хочешхочешь ---. Например, для объекта \verb|Сотрудник| мы можэтможет быть следующий метод иницыализацыиинициализации.
 
<!--
Строка 54:
-->
 
Сотрудник>>иницыализацыяинициализация
сам времяБолезни: 0.
сам время---: 0.
Строка 60:
сам допустимоеВремя---: 80.
 
Для вызова метода \verb|иницыализацыяинициализация| ты должэндолжен переопределить метод \verb|новый| т.к. наследуемый \verb|новый| не вызывает \verb|иницыализацыюинициализацию| (\potom). Обычный способ переопределения \verb|новова| показан в следующем примере (\potom).
 
<!--
Строка 67:
 
класс Сотрудник>>новый
^супер новый иницыализацыяинициализация
 
До того как ты переопределиш \verb|новый| как показано здесь, ты должэндолжен знать что \verb|супер новый| существует. Если метод \verb|новый| в суперкласс посылает сообщение \verb|иницыализацыяинициализация|, твой метод \verb|иницыализацыяинициализация| будет вызван дважды, один раз при вызове метода \verb|новый|, затем второй раз при вызове метода \verb|новый| \emph{Сотрудника}. В этой ситуацыиситуации ты не должэндолжен переопределять \verb|новый| пока ты можэшможешь наследовать его из суперкласса. Т.к. в суперклассе есть метод \verb|иницыализацыяинициализация| предположытельно иницыализируетинициализирует данные суперкласса, твой метод \verb|иницыализацыяинициализация| должэндолжен начинаться со строки \verb|супер иницыализацыяинициализация|. Например, допустим что есть класс \emph{Сотрудник}, с подклассами \emph{ВременныйСотрудник} и \emph{ШтатныйСотрудник}. Давай примем что временный сотрудник работает две недели а штатный сотрудник работает три недели. Мы можэмможем получить следующее:
 
<!--
Строка 77:
 
класс Сотрудник>>новый
^супер новый иницыализацыяинициализация
 
Сотрудник>>иницыализацыяинициализация
сам продолжытельностьБолезни: 0.
сам продолжытельностьРаботы: 0.
 
ВременныйСотрудник>>иницыализацыяинициализация
супер иницыализацыяинициализация
сам допустимоеВремяБолезни: 80.
сам допустимоеВремяРаботы: 80.
 
ШтатныйСотрудник>>иницыализацыяинициализация
супер иницыализацыяинициализация
сам допустимоеВремяБолезни: 120.
сам допустимоеВремяРаботы: 120.
 
Обычный способ сделать переопределения метода \verb|новый| --- \verb|^супер| \verb|новый| \verb|иницыализацыяинициализация|, некоторые люди предпочитают сообщение \verb|простойНовый|.
 
<!--
Строка 101:
 
класс МойКласс>>новый
^сам простойНовый иницыализацыяинициализация
 
Методы которые начинаются с \verb|простой|, таких как \verb|проснойНовый| и \verb|простойОт:|, не могут быт переопределены. Их предназначение предоставлять основную функцыональностьфункциональность, и программисты дожны быть способны полагаться на это. Если ты хочешхочешь переопределить функцыональностьфункциональность, переопредели \verb|новый| и \verb|от:|. При использовании \verb|простойНовый|, ты не должэндолжен беспокоиться о том что любой суперкласс пошлёт сообщение \verb|иницыализацыяинициализация| и из за этого твой метод \verb|иницыализацыяинициализация| выполнится более чем один раз. Однако, ты по прежнему определяеш когда ты должэндолжен посылать сообщение \verb|супер иницыализацыяинициализация| в своём методе \verb|иницыализацыяинициализация|.
 
<!--
Строка 113:
==Переопределение метода новый==
 
\potom. Одно из решэнийрешений --- наследовать все классы твоей программы от \verb|МояПрограммаОбъект|, который заменяет \verb|Объект|. В объекте МояПрограммаОбъект, ты переопределяеш метод \verb|новый| на стороне класса, и пишыш метод \verb|иницыализацыяинициализация| на стороне экзэмпляраэкземпляра. Сейчас ты можэшможешь переопределить \verb|иницыализацыюинициализацию| в твоём классе без переопределения метода \verb|новый|.
 
<!--
Строка 120:
 
класс МояПрограммаОбъект>>новый
^супер просойНовый иницыализацыяинициализация
 
МояПрограммаОбъект>>иницыализацыяинициализация
"ничего не делать"
 
==Присвоение экзэмплярамэкземплярам особых значений==
 
Часто, когда ты создаёшсоздаёшь новый экзэмплярэкземпляр, ты нужнаешсянуждаешься в присвоении ему некоторой информацыиинформации. В нашэмнашем примере сотрудника, мы нуждаемся менее всего в имени. Мы такжэтакже возможно нуждаемся в задании номера соцыальнойсоциальной страховки, зарплаты и информацыиинформации о поле, материальном положэнииположении и количестве ---. Есть два пути: создать экзэмплярэкземпляр а затем присвоить значения переменым, или задать переменные во время создания экзэмпляраэкземпляра. For the sake of example, давай примем что когда создаётся объект сотрудник, две части информацыиинформации абсолютно необходимы: имя и номер соцыальногосоциального страхования. Если мы создадим экзэмплярэкземпляр затем присвоим переменные, мы возможно поступим как-нибудь так:
 
<!--
Строка 136:
сотрудник := Сотрудник новый.
сотрудник := имя: аИмя.
сотрудник номерСоцыальногоСтрахованияномерСоциальногоСтрахования: аНомер.
 
Проблема этого подхода в том, что ты полагаешся на то, что все программисты не будут забывать присвоить требуемые переменные поселпосле создания экзэмпляраэкземпляра. Это нормально, если переменныепеременная необязательная, но опасно, если она обязательная. Если ты хочешхочешь гарантировать, что данные присвоены, лучшэлучше (better off) написать метод создания экзэмпляраэкземпляра который заставляет программиста предоставить нужную информацыюинформацию. Например, если мы напишымнапишем наш собственный метод создания, мы можэмможем создать сотрудникак как здесь:
 
<!--
Строка 144:
-->
 
сотрудник := Сотрудник имя: аИмя номерСоцыальнойСтраховкиномерСоциальнойСтраховки: аНомер
 
Как должэндолжен выглядеть метод \verb|имя:номерСоцыальноСтраховкиномерСоциальноСтраховки:|? Один из вариантов - просто передть методу иницыализацыиинициализации информацыюинформацию, которую нужно присвоить.
 
<!--
Строка 153:
-->
 
класс Сотрудник>>имя: аИмя номерСоцыальнойСтраховкиномерСоциальнойСтраховки: аНомер
^супер новый иницыализироватьИмяинициализироватьИмя: аИмя
номерСоцыальноСтраховкиномерСоциальноСтраховки: аНомер
 
Это разумный подход, если тебе нужэннужен метод иницыализацыиинициализации для других данных, таких как переменнапеременная vocationHoursUsed, показанаяпоказанная вышэвыше. Однако, если метод иницыализацыиинициализации не делает ничего, кроме присвоения переменным подходящих значений, ты можэшможешь присвоить данные непосредственно. Например, ты можэшможешь использовать одну из следующих техник; ---.
 
<!--
Строка 163:
-->
 
класс Сотрудник>>имя: аИмя номерСоцыальногоСтрахованияномерСоциальногоСтрахования: аНомер
| экзэмплярэкземпляр |
экзэмплярэкземпляр := супер новый.
экзэмплярэкземпляр имя: аИмя.
экзэмплярэкземпляр номерСоцыальногоСтрахованияномерСоциальногоСтрахования: аНомер.
^экземпляр
^экзэмпляр
 
класс Сотрудник>>имя: аИмя номерСоцыальногоСтрахованияномерСоциальногоСтрахования: аНомер
^супер новый
имя: аИмя;
номерСоцыальногоСтрахованияномерСоциальногоСтрахования: аНомер;
тысам
 
==Переопределение метода новый для предотвращения его использования==
 
Если ты требуештребуешь от программистов использовать \verb|имя:номерСоцыальногоСтрахованияномерСоциальногоСтрахования:| для создания экзэмпляраэкземпляра \emph{Сотрудник}, ты можэшможешь переопределить \verb|новый| так чтобы он вызывал исключение. Этот способ не очень общий, но он позволяет программисту легко определить, что он неправильно создаёт экзэмплярэкземпляр объекта сотрудник.
 
<!--
Строка 187:
класс Сотрудник>>новый
сам ошыбка:'Пожалуйста используй
имя:номерСоцыальногоСтрахованияномерСоциальногоСтрахования:
для создания экзэмпляровэкземпляров Сотрудник'
 
==Опасайтесь использовать метод новый:==
 
Если только нужно имя сотрудника, ты можэшможешь временно использовать \verb|новый: аИмя|. Воздержывайтесь от временных решэнийрешений. Метод создания экзэмпляраэкземпляра \verb|новый:| используется для задания размера совокупности, и программисты читающие код должны able to assume что создаётся совокупность когда они видят \verb|новый:|. Вместо этого используй \verb|имя:| или \verb|новыйИменуемый:| или \verb|новыйСИменем:|. Я склоняюсь использовать имена методов, которые говорят мне обе вещи: что они создают новый экзэмплярэкземпляр и что параметр означает.
 
<!--
Строка 199:
-->
 
==Классы с единственным экзэмпляромэкземпляром==
 
Некоторые классы имеют только один экзэмплярэкземпляр. Примерами из системных классов являются \verb|истина|, которая является единственым экзэмпляромэкземпляром класса \verb|Истина|, \verb|лож|, экзэмплярэкземпляр \verb|Лож|, \verb|пусто|, экзэмплярэкземпляр \verb|НеопределённыйОбъект|, и \verb|Процэссор|, экзэмплярэкземпляр \verb|ПланировщикПроцэссора|. Классы \verb|НеопределённыйОбъект|, \verb|Логиче--| и \verb|ПланировщикПроцэссора| переопределяют метод \verb|новый| для предотвращения создания экзэмпляровэкземпляров.
 
<!--
Строка 207:
-->
 
В твоём собственном коде, если у тебя есть класс который должэндолжен иметь только один экзэмплярэкземпляр, самым простым способом добиться этого завести переменную класса которая содержыт единственный экзэмплярэкземпляр. Когда кто-нибудь попытается создать новый экзэмплярэкземпляр после того как создан первый, ты можэшможешь или вызвать ошыбку или возвратить первый экзэмплярэкземпляр. Например,
 
<!--
Строка 214:
 
класс МойКласс>>новый
Экзэмплярэкземпляр пусто? лож? [сам ошыбка: 'Ты можэшможешь использовать
только один экзэмплярэкземпляр МоегоКласса'].
Экзэмплярэкземпляр := сам проснойНовый.
^экземпляр
^Экзэмпляр
 
класс МойКласс>>новый
^Экзэмплярэкземпляр пусто?
истина? [Экзэмплярэкземпляр := сам простойНовый]
лож? [Экзэмплярэкземпляр]
 
[[Smalltalk в примерах/Специальные переменные, буквы и символы|Специальные переменные, буквы и
символы >]]
[[Категория:Smalltalk в примерах|Создание экземпляра]]