Переменные — различия между версиями

Материал из Deeptown Manual
Перейти к: навигация, поиск
(minor updates)
 
(не показаны 154 промежуточные версии 29 участников)
Строка 1: Строка 1:
The Car Wash Song, http://tpidxzuas.blogger.hu/2012/07/22/2012-olympics-people 2012 Olympics People,  >:[[[, http://oamoocgry.bloguez.com/oamoocgry/5525202/Hints-For-Alchmy-Ipad Hints For Alchmy Ipad,  =], http://yuwmkbryd.bloguez.com/yuwmkbryd/5521623/Patriots-Championship-Ring-Replica Patriots Championship Ring Replica,  :-PP, http://cqmtpvxfv.bloguez.com/cqmtpvxfv/5529555/1937-Jaguar-Replica 1937 Jaguar Replica,  83581, http://bywjtjfkg.bloguez.com/bywjtjfkg/5523531/Best-Vacheron-Patrimony-Replica-Watch Best Vacheron Patrimony Replica Watch,  330522, http://lcqcjgqmr.bloguez.com/lcqcjgqmr/5520244/Civil-War-Cannon-Replicas-Plans Civil War Cannon Replicas Plans,  cbquwp, http://weigecpgo.bloguez.com/weigecpgo/5525929/Electronic-Cigarette-Environment Electronic Cigarette Environment,  06773, http://eolfxata.bloguez.com/eolfxata/5519718/Electronic-Cigarette-Affiliate-Programs Electronic Cigarette Affiliate Programs,  478641, http://dykcynkpmr.blogger.hu/2012/07/22/whelan-dragons Whelan Dragons,  327874, http://njwmrkmjek.bloguez.com/njwmrkmjek/5518861/Dolce-And-Gabana-Replica Dolce And Gabana Replica,  3146, http://kjtxbpeh.bloguez.com/kjtxbpeh/5531591/Made-In-Usa-Electronic-Cigarettes Made In Usa Electronic Cigarettes,  760, http://vcupriks.bloguez.com/vcupriks/5519726/Mineral-Crystal-Replica Mineral Crystal Replica,  >:-), http://rnmuzgldz.bloguez.com/rnmuzgldz/5522739/Which-Is-The-Best-E-Cigarette-Reviews Which Is The Best E Cigarette Reviews,  8011, http://ansbxwvdm.bloguez.com/ansbxwvdm/5533549/Replica-1903-A4-Sniper-Rifle Replica 1903 A4 Sniper Rifle,  >:-O, http://czmpmjmvg.bloguez.com/czmpmjmvg/5532158/Louis-Ck-London-2012 Louis Ck London 2012,  :-], http://hbumtrwmc.blogger.hu/2012/07/22/magic-prne-oven Magic Prne Oven,  rohj, http://huntmmylf.blogger.hu/2012/07/22/2012-olympics-participants 2012 Olympics Participants,  =-DDD, http://nzimifthw.bloguez.com/nzimifthw/5529042/Electronic-Cigarette-Benefits-Wiki Electronic Cigarette Benefits Wiki,  rncd, http://ptmyvtnl.bloguez.com/ptmyvtnl/5530097/Olympic-Games-Opening-Ceremony-Ticket-Prices Olympic Games Opening Ceremony Ticket Prices,  cfuv, http://dgrhxvpihu.bloguez.com/dgrhxvpihu/5526545/Tin-Ceiling-Tile-Replica Tin Ceiling Tile Replica,  %-), http://ukvxkjzu.bloguez.com/ukvxkjzu/5519468/How-To-Electronic-Cigarettes-Work How To Electronic Cigarettes Work,  3378, http://hdlrqvpmp.bloguez.com/hdlrqvpmp/5525140/Fantasy-Sword-Replicas Fantasy Sword Replicas,  lshrqr,
+
__TOC__
 +
== Понятие переменной, тип переменной ==
  
== What Is Your Legacy? Living A Meaningful life ==
+
В классических книгах по программированию, под переменными понимают некоторую поименованную область памяти, либо регистр процессора. В нашем же случае, мы имеем дело с виртуальной машиной, соответственно ни регистров, ни памяти в обычном понимании у нас нет. Все, с чем мы имеем дело, это с объектами в "сознании" виртуальной машины. Так или иначе, но и там и тут переменные служат для одной цели: для хранения некоторой информации. Ей могут быть и исходные данные программы, и некоторые промежуточные значения, или же результаты выполнения программы. Впрочем, некоторые программы могут не иметь исходных данных (например, генератор текстур), другие же могут не производить никакого вывода, так что все это довольно условно.
  
I want the world to be better because I was here. I want my life, I want my work, my family, I want it to mean something and if you are not making someone elses life better then you are wasting your time Will Smith
+
Поэтому, будем считать проще, что переменная это просто некоторая сущность, некоторый объект, способный хранить данные. Под данными мы будем понимать любую информацию, которую возможно представить в цифровом виде.
  
[[http://goodvillenews.com/What-Is-Your-Legacy-Living-A-Meaningful-life-oBtnrB.html What Is Your Legacy? Living A Meaningful life]]
+
=== Тип переменной ===
  
[[http://goodvillenews.com/wk.html GoodvilleNews.com - good, positive news, inspirational stories, articles]]
+
Часто с понятием переменной связывают понятие ее типа. Стоит отметить, что это понятие так же является математической абстракцией. С точки зрения самой машины все данные представляют собой одно и то же — совокупность нулей и единиц. А что под ними понимать в каждом конкретном случае — решает уже программист. Так вот, в некотором смысле ''тип переменной'' показывает, что именно хранится в данной переменной.
  
== How To Speak More Wisely ==
+
Наиболее распространенные типы переменных это:
 +
* Логический тип, принимающий только два значения ("истина" и "ложь")
 +
* Целые числа различной длины (байт, слово, двойное слово и т. д.)
 +
* Числа с плавающей точкой
 +
* Строки (последовательность байтов в памяти, воспринимаемая как строка текста)
 +
* Указатели (переменные, содержащие в себе адрес другой переменной)
 +
* Составные типы (некоторая совокупность из вышеперечисленных типов)
  
It had been three weeks since my throat started to feel sore, and it wasnt getting better. The pain was most acute when I spoke. So I decided to spend a few days speaking as little as possible. Every time I had the urge to say something, I paused for a moment to question whether it was worth irritating my throat.
+
Как уже говорилось выше, первоначально о типе переменной знал только программист, пишущий программу. Естественно, вся ответственность за соблюдение соответствия типов выполняемым операциям была возложена на самого программиста. Постепенно, с развитием языков программирования высокого уровня, была выдвинута идея явным образом сопоставлять переменной ее тип. Это обеспечивало большее удобство в написании программ, поскольку всю работу по контролю над типами выполнял сам компилятор, который выдавал сообщения об ошибках, если типы переменных не соответствовали операциям, или была вероятность неверного их истолкования. Так появились языки со статической типизацией.
  
[[http://goodvillenews.com/How-To-Speak-More-Wisely-86itqo.html How To Speak More Wisely]]
+
== Статическая типизация на примере C++ ==
  
[[http://goodvillenews.com/wk.html GoodvilleNews.com - good, positive news, inspirational stories, articles]]
+
Итак, ''статическая типизация'' это — приём, при котором переменная, параметр подпрограммы или возвращаемое значение функции связывается с типом в момент объявления и этот тип не может быть изменён позже (переменная или параметр будут принимать, а функция будет возвращать значения только этого типа).
  
== Bangladesh rickshaw puller starts clinic for the poor ==
+
То есть, если мы объявляем переменные целочисленного типа как <tt>int i, j;</tt> то мы можем выполнять над ними только операции, соответствующие понятиям этого типа, вроде операции сложения <tt>i + j</tt> или операции присваивания одной переменной другой <tt>i = j</tt>. Если же мы попытаемся присвоить такой переменной значение другого, ''неприводимого'' типа, например <tt>i = [2, 3]</tt> то компилятор выдаст ошибку.
  
Joynal Abedin still remembers the rainy and windy night when he saw his father die because there was no medical treatment. His village in the northern Mymensingh district of Bangladesh did not have any medical facility at that time, and the nearest hospital was about 20km (12 miles) away.
+
Рассмотрим кратко преимущества и недостатки статически типированных языков и сравним их впоследствии с другими подходами к типизации.
  
[[http://goodvillenews.com/Bangladesh-rickshaw-puller-starts-clinic-for-the-poor-0zbEXF.html Bangladesh rickshaw puller starts clinic for the poor]]
+
Преимущества статической типизации:
 +
* Строгость программ
 +
* Большая возможность оптимизации, а, следовательно:
 +
** Высокая скорость работы
 +
** Минимальные требования к памяти
  
[[http://goodvillenews.com/wk.html GoodvilleNews.com - good, positive news, inspirational stories, articles]]
+
Недостатки:
 +
* Необходимость объявления типов даже там где это очевидно
 +
* Засорение кода программы дополнительными символами, а, следовательно:
 +
** Отвлечение внимания программиста от самой задачи в сторону рутины формализации
 +
** Плохая читаемость кода
 +
* Необходимость дополнительных ухищрений для передачи параметров разных типов
 +
* Невозможность написания абстрактных алгоритмов
  
== Pilgrims for Peace: One Couples Incredible Journey ==
+
'''Вывод:''' Программы, написанные на языках со статической типизацией, обладают большой эффективностью и производительностью, однако это дается ценой строгости и определенности. Программирование на таких языках это принятие их правил игры, при этом программист должен мыслить в жестко ограниченных рамках. Вот почему эти языки чаще всего применяются именно для системного программирования, где в первую очередь важна производительность полученного кода, и только потом удобство его написания и поддержки.
  
"In the life of each and every one of us, there is a defining moment, one after which we know that our lives will never be the same. For me, 9/11 was that moment." Mony Dojeijis defining moment eventually led her to an ancient pilgrimage route in Spain, where a chance encounter with an artist would change both of their lives forever. Together they would end up walking a pilgrimage for peace in Jerusalem -- and in the process would uncover precious insights about themselves, each other and the goodness of humanity.
+
== Динамическая типизация на примере Ruby ==
  
[[http://goodvillenews.com/Pilgrims-for-Peace-One-Couples-Incredible-Journey-FMm6R6.html Pilgrims for Peace: One Couples Incredible Journey]]
+
Впоследствии, в противовес статической типизации была разработана модель динамически типированных языков. При таком подходе, переменная не имеет заранее определенного типа, а принимает тип при инициализации и при присвоении ей некоторого значения. Таким образом, в различных участках программы одна и та же переменная может принимать значения разных типов.  
  
[[http://goodvillenews.com/wk.html GoodvilleNews.com - good, positive news, inspirational stories, articles]]
+
На первый взгляд это может показать странным, особенно с точки зрения программиста, привыкшего к статически типированным языкам (таким как С++ или Паскаль). На самом деле здесь нет ничего страшного или нелогичного. Все мы в своей жизни, сами того не подозревая, оперируем понятиями динамических переменных. Один и тот же объект в разных ситуациях мы можем воспринимать с разных точек зрения. Задавая вопрос "как пройти в библиотеку", мы можем получить как конкретный ответ "в 3 часа ночи?! идиот!" так и целый набор: "на автобусе номер 23, на такси или пешком, тут не очень далеко". При этом нас совершенно не смущает то, что мы заранее не знаем, каков будет результат, наоборот — это дает нам большую гибкость и свободу действий; мы двигаемся дальше на основании того, каков был результат предыдущей операции. Подобно этому примеру, мы можем писать программы, которые оперируют переменными неопределенного типа. В результате, код получается более лаконичным, более читаемым и, в конце концов, более близким к естественному восприятию человека (ведь именно этого мы ждем от языков программирования!).
  
== The Power of Words and Emotional Bonding! ==
+
Концепция динамической типизации в полной мере нашла свое применение в языке Ruby. В этом языке любая переменная может в разное время иметь различные типы. Вот пример кода на этом языке:
  
If you become steadfast in your abstentions of thoughts of harm directed toward others, all living creatures will cease to feel enmity in your presence. PatanjaliWords have power, incredible power, and this power lies in each and every one of us. Of course, its up to us to use this power for the greater good of all or not.
+
<source lang="ruby">
 +
def get_data(need_array = false)
 +
  result = 0    # целое число
 +
  if need_array
 +
    result = [ 1, 2, 3, 4 ]  # тип меняется на Array
 +
  else
 +
    result = { 1 => 2, 3 => 4}  # тип меняется на Hash
 +
  end
 +
  result
 +
end
 +
</source>
  
[[http://goodvillenews.com/The-Power-of-Words-and-Emotional-Bonding-2wgncv.html The Power of Words and Emotional Bonding!]]
+
Преимущества динамической типизации:
 +
* Легкость написания программ
 +
* Лаконичность и хорошая читаемость
 +
* Высокая гибкость языка. Возможность решения проблемы разными способами
 +
* Большая возможность повторного использования кода (абстрактные алгоритмы)
  
[[http://goodvillenews.com/wk.html GoodvilleNews.com - good, positive news, inspirational stories, articles]]
+
Недостатки:
 +
* Существенно меньшая производительность, по сравнению со статически типированными языками
 +
* Сложность в написании оптимизаторов, их малая эффективность
 +
* Как правило, динамически типированные языки являются интерпретаторами (компиляция не столь эффективна)
 +
 
 +
'''Вывод:''' Языки с динамической типизацией очень удобны для использования на прикладном уровне. Учитывая их высокую гибкость и лаконичность, программисту легче излагать свои мысли, при том, что свое внимание он концентрирует на самой задаче, не отвлекаясь на частные проблемы реализации. Конечно, они уступают по эффективности статическим, компилируемым языкам, однако это уже вопрос, требующий отдельного рассмотрения в рамках конкретно поставленной задачи.
 +
 
 +
== Полудинамическая типизация ==
 +
 
 +
Рассмотрев преимущества и недостатки статической и динамической типизации, мы подходим к мысли объединения этих двух подходов в рамках одного языка. Языка, который бы сочетал в себе все преимущества динамической типизации, с возможностью указания типов там, где это необходимо. В результате мы получили бы язык, достаточно гибкий и в то же время позволяющий эффективно работать с типами.
 +
 
 +
Язык К++ как раз и ставит перед собой задачу совмещения этих двух подходов. Переменные этого языка могут быть либо типированными, либо не типированными (динамическими). Первые обеспечивают производительность, вторые — гибкость. Достигается это, прежде всего ценой того, что переменная не может изменять свой тип во время выполнения программы. Однако это относится только к статически типированным переменным. Полностью динамические переменные этого недостатка лишены.
 +
 
 +
При разработке программы на языке К++, программист должен стараться держать баланс между удобством написания программы и ее эффективностью. В целом, рекомендуется указывать типы переменных везде, где это возможно. Динамические же переменные следует применять в тех местах, где заранее неизвестно, с каким типом переменной придется работать.
 +
 
 +
== Типизация при объявлении ==
 +
 
 +
Язык К++ позволяет задавать тип переменной несколькими способами. Одним из них является типирование переменной при объявлении. При этом необходимо написать ключевое слово <tt>'''var'''</tt>, за которым следует [[идентификатор]] типа переменной, а затем ее имя. Точка с запятой (;) завершает конструкцию:
 +
 
 +
<source lang="kpp">
 +
var int i;
 +
</source>
 +
 
 +
Здесь мы объявили [[Стандартные типы данных#Числа|целочисленную]] переменную с именем ''i'' и неявно [[Инициализация|инициализировали]] ее значением 0. Такой синтаксис удобен в тех случаях, когда заранее неизвестно каким должно быть значение переменной. Видимо, в данном случае программист решил, что оно будет присвоено явным образом впоследствии. Если же заранее ясно, что на момент объявления переменная должна иметь определенное значение, следует применять синтаксис ''объявления с инициализацией''.
 +
 
 +
'''Примечание:''' Неявная инициализация это причина многих трудноуловимых ошибок времени выполнения. В языке К++ это имеет менее разрушительные последствия, чем например в С++ (где значение неинициализированной переменной может быть абсолютно произвольным!), тем не менее '''настоятельно рекомендуется инициализировать переменные''' сразу при объявлении. Это избавит вас от опасности забыть присвоить значение переменной впоследствии.
 +
 
 +
== Типизация при инициализации ==
 +
 
 +
Более предпочтительным способом объявления типированной переменной является ''объявление с инициализацией''. В данном случае, под ''инициализацией'' понимается процесс начального задания значения переменной. Для этого следует так же написать ключевое слово <tt>'''var'''</tt>, после которого сразу идет [[идентификатор]] имени переменной, а затем выражение — инициализатор, присваивающее значение вновь созданной переменной. При этом тип переменной будет определен как тип инициализатора:
 +
 
 +
<source lang="kpp">
 +
var i = 0;
 +
var s = "hello world";
 +
</source>
 +
 
 +
В приведенном выше примере, переменной ''i'' будет назначен целочисленный тип (<tt>[[Стандартные типы данных#Целые числа|int]]</tt>), в то время как переменная ''s'' будет иметь строковый тип (<tt>[[Стандартные типы данных#Строки|string]]</tt>).
 +
 
 +
'''Примечание:''' В некоторых случаях может сложиться ситуация, что инициализатор переменной это довольно сложное выражение. При этом программисту сложно определить, какой же на самом деле будет тип переменной. Для ясности приведем пример из разряда "как не надо делать":
 +
 
 +
<source lang="kpp">
 +
var x = 2+3*4+f(3)/3*0.2;
 +
</source>
 +
 
 +
Синтаксически здесь все верно. Переменная будет создана и ей будет назначен некоторый тип. Но вот какой? Опытный читатель заметит, что в выражении присутствуют константы с плавающей точкой и операция деления. Стало быть, в результате [[Приведение типов|приведения типов]], результирующий тип переменной так же будет [[Стандартные типы данных#Числа с плавающей точкой|числом с плавающей точкой]]. Внимательный же читатель заметит так же, что в выражении присутствует [[Выражения#Вызов функций|вызов функции]] <tt>f(3)</tt>. И тут дело обстоит еще хуже. [[Функции|Функция]] может возвращать значение любого типа. Чтобы узнать какого именно, нужно обратиться к документации, либо к описанию самой функции. А что если она возвращает нетипированную переменную ([[Переменные#Нетипированные (динамические) переменные|см. ниже]])? Тогда предсказать тип переменной будет еще сложнее (если забежать вперед, то можно сказать что результат выражения так же будет нетипирован).
 +
 
 +
Скорее всего, Читатель уже согласился с мыслью, что подобных конструкций следует избегать. Однако что же делать, если все же требуется завести переменную, которая должна быть инициализирована подобным образом? Выхода тут может быть два. Либо отделить объявление переменной от ее инициализации, либо совместить типированное объявление с инициализацией.
 +
 
 +
Первый вариант:
 +
<source lang="kpp">
 +
var real x;
 +
... //где то по коду программы
 +
x = 2+3*4+f(3)/3*0.2;
 +
</source>
 +
 
 +
Второй, более удачный вариант:
 +
<source lang="kpp">
 +
var real x = 2+3*4+f(3)/3*0.2;
 +
</source>
 +
 
 +
Стоит отметить, что во втором случае будет выполнена операция [[Приведение типов|приведения типов]], то есть будет сделана попытка преобразовать тип значения инициализатора к явно указанному типу переменной. Если тип инициализатора возможно ''привести'' к типу переменной, то все пройдет успешно. Если же типы ''неприводимы'', то произойдет либо ошибка компиляции (при статическом типе инициализатора), либо ошибка времени выполнения (при динамическом).
 +
 
 +
== Нетипированные (динамические) переменные ==
 +
 
 +
Иногда бывает необходимо работать с переменной, тип которой на момент компиляции неизвестен. В этом случае применяются ''нетипированные'' или ''динамические'' переменные. Такие переменные объявляются просто, путем написания ключевого слова <tt>'''var'''</tt>, за которым идет [[идентификатор]] имени переменной:
 +
 
 +
<source lang="kpp">
 +
var x;
 +
</source>
 +
 
 +
В ходе работы программы, такая переменная может принимать значения любых типов. Она будет автоматически приводиться к нужным типам (и наоборот), что, в конечном счете, обеспечивает гибкость кода.
 +
 
 +
Примером применения динамических переменных могут послужить контейнеры — объекты, которые могут хранить в себе другие объекты. Простейшими примерами контейнеров могут послужить [[Стандартные типы данных#Массивы|массивы]]. В языке К++ массивы не являются типированными. Они могут хранить любые объекты, даже объекты различных типов. Разумеется, сам массив оперирует со своими элементами как с нетипированными переменными (ведь он не знает заранее, объекты каких типов будут в него класть).
 +
 
 +
Программист может написать некоторую подпрограмму для обработки элементов массива, например для их сортировки. При этом все, что ему нужно знать это способ перебора элементов контейнера и некоторую операцию сравнения двух элементов, для выяснения их очередности (эту операцию контейнеру предоставляет пользователь; как именно это делается, будет описано [[Блоки#Применение блоков|позднее]]). Этим достигается эффективность написания кода, и открываются широкие возможности по повторному использованию кода. К примеру, в традиционных типированных языках вроде Паскаля, пришлось бы реализовывать отдельные методы сортировки строк, числовых массивов и т. д., здесь же мы обходимся одной реализацией.
 +
 
 +
== О важности инициализации переменных ==
 +
 
 +
В заключение этой главы, приведем краткое обобщение материала относительно инициализации переменных. Как уже было сказано выше, инициализация переменных это важный момент, правильное понимание которого позволит программисту писать более эффективные программы, и в то же время избавить себя от многих типичных ошибок программирования. В ходе изучения языка постарайтесь выработать у себя некоторые шаблоны проектирования, следуя которым вы избавите себя от возможных проблем.
 +
 
 +
Вот некоторый список рекомендаций относительно объявления переменных:
 +
* Старайтесь всегда объявлять переменные, инициализируя их
 +
* Если выражение инициализатора достаточно сложное, либо содержит вызовы функций, применяйте явное типирование объявляемой переменной, либо используйте [[приведение типов]] в самом выражении
 +
* Объявляйте переменные как можно ближе к месту их использования
 +
* Нетипированные переменные применяйте только в тех случаях, где это действительно необходимо
 +
 
 +
Конечно, этот список далеко не полный, да он и не претендует на полноту. То, что написано выше ни в коем случае не является правилом, которому нужно следовать непременно, везде и всегда. Границы разумного определяете вы сами. Просто старайтесь не упускать этих моментов из виду.

Текущая версия на 15:02, 13 июля 2013

Содержание

[править] Понятие переменной, тип переменной

В классических книгах по программированию, под переменными понимают некоторую поименованную область памяти, либо регистр процессора. В нашем же случае, мы имеем дело с виртуальной машиной, соответственно ни регистров, ни памяти в обычном понимании у нас нет. Все, с чем мы имеем дело, это с объектами в "сознании" виртуальной машины. Так или иначе, но и там и тут переменные служат для одной цели: для хранения некоторой информации. Ей могут быть и исходные данные программы, и некоторые промежуточные значения, или же результаты выполнения программы. Впрочем, некоторые программы могут не иметь исходных данных (например, генератор текстур), другие же могут не производить никакого вывода, так что все это довольно условно.

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

[править] Тип переменной

Часто с понятием переменной связывают понятие ее типа. Стоит отметить, что это понятие так же является математической абстракцией. С точки зрения самой машины все данные представляют собой одно и то же — совокупность нулей и единиц. А что под ними понимать в каждом конкретном случае — решает уже программист. Так вот, в некотором смысле тип переменной показывает, что именно хранится в данной переменной.

Наиболее распространенные типы переменных это:

  • Логический тип, принимающий только два значения ("истина" и "ложь")
  • Целые числа различной длины (байт, слово, двойное слово и т. д.)
  • Числа с плавающей точкой
  • Строки (последовательность байтов в памяти, воспринимаемая как строка текста)
  • Указатели (переменные, содержащие в себе адрес другой переменной)
  • Составные типы (некоторая совокупность из вышеперечисленных типов)

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

[править] Статическая типизация на примере C++

Итак, статическая типизация это — приём, при котором переменная, параметр подпрограммы или возвращаемое значение функции связывается с типом в момент объявления и этот тип не может быть изменён позже (переменная или параметр будут принимать, а функция будет возвращать значения только этого типа).

То есть, если мы объявляем переменные целочисленного типа как int i, j; то мы можем выполнять над ними только операции, соответствующие понятиям этого типа, вроде операции сложения i + j или операции присваивания одной переменной другой i = j. Если же мы попытаемся присвоить такой переменной значение другого, неприводимого типа, например i = [2, 3] то компилятор выдаст ошибку.

Рассмотрим кратко преимущества и недостатки статически типированных языков и сравним их впоследствии с другими подходами к типизации.

Преимущества статической типизации:

  • Строгость программ
  • Большая возможность оптимизации, а, следовательно:
    • Высокая скорость работы
    • Минимальные требования к памяти

Недостатки:

  • Необходимость объявления типов даже там где это очевидно
  • Засорение кода программы дополнительными символами, а, следовательно:
    • Отвлечение внимания программиста от самой задачи в сторону рутины формализации
    • Плохая читаемость кода
  • Необходимость дополнительных ухищрений для передачи параметров разных типов
  • Невозможность написания абстрактных алгоритмов

Вывод: Программы, написанные на языках со статической типизацией, обладают большой эффективностью и производительностью, однако это дается ценой строгости и определенности. Программирование на таких языках это принятие их правил игры, при этом программист должен мыслить в жестко ограниченных рамках. Вот почему эти языки чаще всего применяются именно для системного программирования, где в первую очередь важна производительность полученного кода, и только потом удобство его написания и поддержки.

[править] Динамическая типизация на примере Ruby

Впоследствии, в противовес статической типизации была разработана модель динамически типированных языков. При таком подходе, переменная не имеет заранее определенного типа, а принимает тип при инициализации и при присвоении ей некоторого значения. Таким образом, в различных участках программы одна и та же переменная может принимать значения разных типов.

На первый взгляд это может показать странным, особенно с точки зрения программиста, привыкшего к статически типированным языкам (таким как С++ или Паскаль). На самом деле здесь нет ничего страшного или нелогичного. Все мы в своей жизни, сами того не подозревая, оперируем понятиями динамических переменных. Один и тот же объект в разных ситуациях мы можем воспринимать с разных точек зрения. Задавая вопрос "как пройти в библиотеку", мы можем получить как конкретный ответ "в 3 часа ночи?! идиот!" так и целый набор: "на автобусе номер 23, на такси или пешком, тут не очень далеко". При этом нас совершенно не смущает то, что мы заранее не знаем, каков будет результат, наоборот — это дает нам большую гибкость и свободу действий; мы двигаемся дальше на основании того, каков был результат предыдущей операции. Подобно этому примеру, мы можем писать программы, которые оперируют переменными неопределенного типа. В результате, код получается более лаконичным, более читаемым и, в конце концов, более близким к естественному восприятию человека (ведь именно этого мы ждем от языков программирования!).

Концепция динамической типизации в полной мере нашла свое применение в языке Ruby. В этом языке любая переменная может в разное время иметь различные типы. Вот пример кода на этом языке:

<source lang="ruby"> def get_data(need_array = false)

 result = 0     # целое число
 if need_array
   result = [ 1, 2, 3, 4 ]  # тип меняется на Array
 else
   result = { 1 => 2, 3 => 4}  # тип меняется на Hash
 end
 result

end </source>

Преимущества динамической типизации:

  • Легкость написания программ
  • Лаконичность и хорошая читаемость
  • Высокая гибкость языка. Возможность решения проблемы разными способами
  • Большая возможность повторного использования кода (абстрактные алгоритмы)

Недостатки:

  • Существенно меньшая производительность, по сравнению со статически типированными языками
  • Сложность в написании оптимизаторов, их малая эффективность
  • Как правило, динамически типированные языки являются интерпретаторами (компиляция не столь эффективна)

Вывод: Языки с динамической типизацией очень удобны для использования на прикладном уровне. Учитывая их высокую гибкость и лаконичность, программисту легче излагать свои мысли, при том, что свое внимание он концентрирует на самой задаче, не отвлекаясь на частные проблемы реализации. Конечно, они уступают по эффективности статическим, компилируемым языкам, однако это уже вопрос, требующий отдельного рассмотрения в рамках конкретно поставленной задачи.

[править] Полудинамическая типизация

Рассмотрев преимущества и недостатки статической и динамической типизации, мы подходим к мысли объединения этих двух подходов в рамках одного языка. Языка, который бы сочетал в себе все преимущества динамической типизации, с возможностью указания типов там, где это необходимо. В результате мы получили бы язык, достаточно гибкий и в то же время позволяющий эффективно работать с типами.

Язык К++ как раз и ставит перед собой задачу совмещения этих двух подходов. Переменные этого языка могут быть либо типированными, либо не типированными (динамическими). Первые обеспечивают производительность, вторые — гибкость. Достигается это, прежде всего ценой того, что переменная не может изменять свой тип во время выполнения программы. Однако это относится только к статически типированным переменным. Полностью динамические переменные этого недостатка лишены.

При разработке программы на языке К++, программист должен стараться держать баланс между удобством написания программы и ее эффективностью. В целом, рекомендуется указывать типы переменных везде, где это возможно. Динамические же переменные следует применять в тех местах, где заранее неизвестно, с каким типом переменной придется работать.

[править] Типизация при объявлении

Язык К++ позволяет задавать тип переменной несколькими способами. Одним из них является типирование переменной при объявлении. При этом необходимо написать ключевое слово var, за которым следует идентификатор типа переменной, а затем ее имя. Точка с запятой (;) завершает конструкцию:

<source lang="kpp"> var int i; </source>

Здесь мы объявили целочисленную переменную с именем i и неявно инициализировали ее значением 0. Такой синтаксис удобен в тех случаях, когда заранее неизвестно каким должно быть значение переменной. Видимо, в данном случае программист решил, что оно будет присвоено явным образом впоследствии. Если же заранее ясно, что на момент объявления переменная должна иметь определенное значение, следует применять синтаксис объявления с инициализацией.

Примечание: Неявная инициализация это причина многих трудноуловимых ошибок времени выполнения. В языке К++ это имеет менее разрушительные последствия, чем например в С++ (где значение неинициализированной переменной может быть абсолютно произвольным!), тем не менее настоятельно рекомендуется инициализировать переменные сразу при объявлении. Это избавит вас от опасности забыть присвоить значение переменной впоследствии.

[править] Типизация при инициализации

Более предпочтительным способом объявления типированной переменной является объявление с инициализацией. В данном случае, под инициализацией понимается процесс начального задания значения переменной. Для этого следует так же написать ключевое слово var, после которого сразу идет идентификатор имени переменной, а затем выражение — инициализатор, присваивающее значение вновь созданной переменной. При этом тип переменной будет определен как тип инициализатора:

<source lang="kpp"> var i = 0; var s = "hello world"; </source>

В приведенном выше примере, переменной i будет назначен целочисленный тип (int), в то время как переменная s будет иметь строковый тип (string).

Примечание: В некоторых случаях может сложиться ситуация, что инициализатор переменной это довольно сложное выражение. При этом программисту сложно определить, какой же на самом деле будет тип переменной. Для ясности приведем пример из разряда "как не надо делать":

<source lang="kpp"> var x = 2+3*4+f(3)/3*0.2; </source>

Синтаксически здесь все верно. Переменная будет создана и ей будет назначен некоторый тип. Но вот какой? Опытный читатель заметит, что в выражении присутствуют константы с плавающей точкой и операция деления. Стало быть, в результате приведения типов, результирующий тип переменной так же будет числом с плавающей точкой. Внимательный же читатель заметит так же, что в выражении присутствует вызов функции f(3). И тут дело обстоит еще хуже. Функция может возвращать значение любого типа. Чтобы узнать какого именно, нужно обратиться к документации, либо к описанию самой функции. А что если она возвращает нетипированную переменную (см. ниже)? Тогда предсказать тип переменной будет еще сложнее (если забежать вперед, то можно сказать что результат выражения так же будет нетипирован).

Скорее всего, Читатель уже согласился с мыслью, что подобных конструкций следует избегать. Однако что же делать, если все же требуется завести переменную, которая должна быть инициализирована подобным образом? Выхода тут может быть два. Либо отделить объявление переменной от ее инициализации, либо совместить типированное объявление с инициализацией.

Первый вариант: <source lang="kpp"> var real x; ... //где то по коду программы x = 2+3*4+f(3)/3*0.2; </source>

Второй, более удачный вариант: <source lang="kpp"> var real x = 2+3*4+f(3)/3*0.2; </source>

Стоит отметить, что во втором случае будет выполнена операция приведения типов, то есть будет сделана попытка преобразовать тип значения инициализатора к явно указанному типу переменной. Если тип инициализатора возможно привести к типу переменной, то все пройдет успешно. Если же типы неприводимы, то произойдет либо ошибка компиляции (при статическом типе инициализатора), либо ошибка времени выполнения (при динамическом).

[править] Нетипированные (динамические) переменные

Иногда бывает необходимо работать с переменной, тип которой на момент компиляции неизвестен. В этом случае применяются нетипированные или динамические переменные. Такие переменные объявляются просто, путем написания ключевого слова var, за которым идет идентификатор имени переменной:

<source lang="kpp"> var x; </source>

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

Примером применения динамических переменных могут послужить контейнеры — объекты, которые могут хранить в себе другие объекты. Простейшими примерами контейнеров могут послужить массивы. В языке К++ массивы не являются типированными. Они могут хранить любые объекты, даже объекты различных типов. Разумеется, сам массив оперирует со своими элементами как с нетипированными переменными (ведь он не знает заранее, объекты каких типов будут в него класть).

Программист может написать некоторую подпрограмму для обработки элементов массива, например для их сортировки. При этом все, что ему нужно знать это способ перебора элементов контейнера и некоторую операцию сравнения двух элементов, для выяснения их очередности (эту операцию контейнеру предоставляет пользователь; как именно это делается, будет описано позднее). Этим достигается эффективность написания кода, и открываются широкие возможности по повторному использованию кода. К примеру, в традиционных типированных языках вроде Паскаля, пришлось бы реализовывать отдельные методы сортировки строк, числовых массивов и т. д., здесь же мы обходимся одной реализацией.

[править] О важности инициализации переменных

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

Вот некоторый список рекомендаций относительно объявления переменных:

  • Старайтесь всегда объявлять переменные, инициализируя их
  • Если выражение инициализатора достаточно сложное, либо содержит вызовы функций, применяйте явное типирование объявляемой переменной, либо используйте приведение типов в самом выражении
  • Объявляйте переменные как можно ближе к месту их использования
  • Нетипированные переменные применяйте только в тех случаях, где это действительно необходимо

Конечно, этот список далеко не полный, да он и не претендует на полноту. То, что написано выше ни в коем случае не является правилом, которому нужно следовать непременно, везде и всегда. Границы разумного определяете вы сами. Просто старайтесь не упускать этих моментов из виду.

Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
информация
документация
Инструменты