Результат теста "Гарантирую угадать о чем ты думаешь сейчас......." |
|
|
Результат теста "Кто ты в Final Fantasy VII" |
|
|
ах да совсем забыл!!! |
|
|
Цитата сообщения Acryll
Про Даджа и Клауда))))))))) |
Цитата |
|
|
Комментарии (0) |
Без заголовка |
|
|
Ой...... |
|
|
Чертова взрослая поликлиника |
|
|
ЕЩЕ КОЕ ЧТО ДАДЖУ |
|
|
Дадж тебе нашел кое что!!! |
Рубрика: Информатика, программирование |
| Тип работы: доклады |
| Дата добавления: 3.2.2005 |
| Кол-во скачиваний: 86 |
| HTML (3K) |
| RTF (6K) |
CSS дизайн: с учетом контекста
Джошуа Портер
Веб-стандарты обещают нам улучшенную поддержку мультимедиа: возможность оптимизировать контент под возможности компьютерных экранов, портативных устройств, принтеров, проекторов, и других средств.
С помощью CSS сделать это весьма просто. Всё, что вам нужно - импортировать отдельную таблицу стилей для каждого типа устройств, которая переопределит стилевые правила, указанные в основной таблице стилей. Почитайте фантастически важную статью Эрика Мейера "В печать!", где дается подробнейший пример того, как на практике осуществить сказанное выше. (Внимание: некоторые типы устройств поддерживаются не полностью).
В настоящее время в дизайнерском сообществе большая часть дискуссий сфокусирована на проблеме написания стилей для различных типов устройств. Точнее, дизайнеры пытаются сделать контент более доступным, избавляясь от тяжеловесной графики (оптимизация для портативных устройств) или применяя более разборчивые шрифты (подготовка печатной версии).
Мы не хотим останавливаться на достигнутом. Вместо того, чтобы писать разные стили к одному и тому же контенту, но для разных устройств, почему бы не использовать их для показа специфического контента, предназначенного только для текущей ситуации?
Представьте, что дизайнер читает статью из его любимого сетевого журнала, а потом распечатывает её. Дизайнер сшивает страницы, выделяет что-то в тексте, а в процессе чтения ещё и отмечает важные моменты на полях страниц. По прошествии времени он снова обращается к бумажной копии.
Что можем мы сказать об этой ситуации? Есть ли в ней что-то уникальное? На что следует обратить внимание?
Другая среда предлагает другие возможности
Прежде всего, дизайнер из нашего примера читал статью не в той среде, для которой она была создана, используя её таким образом, который немыслим при работе с экраном (ну, например, выделение интересных моментов маркером). Наконец, мы знаем, что дизайнеру эта статья нужна настолько, что он хотел бы иметь её физическую копию. Именно это выделяет его на фоне людей, читающих лишь сетевую версию.
Дизайн для контекста
Скажем, вы хотите использовать для общения с потенциальными посетителями такой контент, который напрямую зависит от текущей ситуации. Что произойдет, когда кто-то, не бывавший на вашем сайте, будет читать распечатку одной из ваших статей? Какое сообщение вы можете до него донести, когда он напечатает статью, при этом спрятав его от тех, кто читает статью с экрана? Если ваша цель - увеличение числа читателей - вы можете написать им что-то вроде:
"Вы видите печатную версию статьи с фантастического веб-сайта (http://www.xyz.com), на котором вы сможете найти море подходящей вам информации. Мы думаем, вам будет интересна ещё одна статья (http://xyz.com/article02.html) по этой же теме".
Если в ваши планы входит увеличение числа зарегистрированных клиентов, напишите, например, вот что:
"Если вы получили эту распечатку от кого-то из ваших друзей или коллег - вы имеете право на особую скидку. Зарегистрируйтесь у нас - и мы дадим вам 10% скидку для первой покупки".
Если вы хотите связаться с людьми, интересующимися услугами вашей компании, напишите нечто подобное:
"Вы читаете статью, написанную юристом компании XYZ. Это - его работа. Если у вас есть какие-то вопросы касательно упомянутых в статье услуг, просто позвоните нашему юристу на персональный номер (321-867-5309 ext 123) и она сможет рассказать о том, что XYZ может сделать для вас".
Предыдущий пример не очень-то подходит для печатной версии, но может быть полезен тем читателям, кто видит ваш контент на экране своего мобильного телефона. Вы же знаете - им несложно позвонить вам.).
Но не выставляйте эти послания на всеобщее обозрение посетителей вашего сайта. Вам не надо показывать их вне контекста - создайте особую ситуацию, в контексте которой ваше послание будет уместным - и люди воспользуются им.
Легким движением CSS...
Напишем несложный CSS код. Сначала создадим div с контентом, специально написанным для тех устройств, ради которых всё и затеяно - пусть, для ясности, это будет печать на принтере:
<div id="offer4print">
<p>Предложение, от которого невозможно отказаться.</p>
</div>
В основной таблице стилей примените к этому блоку свойство display: none;, таким образом он будет невидим при просмотре в Сети (на мониторе компьютера). Для этого в таблицу стилей для монитора (media="screen") включите вот такую строку:
div#offer4print { display: none; }
Теперь запишите в таблицу стилей для печати (впрочем, можете писать и для другого типа устройств - по вашему усмотрению) те стилевые правила, которые вам необходимы:
div#offer4print { //укажите здесь стили для печатной версии }
Несколько идей по созданию печатной версии…
Если вам известно имя читателя (скажем, он зарегистрировался на вашем сайте) - укажите его в печатной версии. Получится, будто эта распечатка сделана специально для него: ex libris Джошуа Портер.
Выдвигайте особые предложения. Помните, эти люди отличаются от основной массы читателей (ведь они не зря распечатали вашу статью) - обращайтесь с ними соответственно и создавайте такой дизайн, который учитывает контекст.
… и версии для портативных устройств:
Номера телефонов (а почему бы и нет? - это ж очевидно). Предложите прямой доступ к информации, связанной с той, что находится в распечатанной ими статье. Люди оценят ваши труды.
Дайте им простой способ получения по электронной почте PDF-версии документа, удобной для просмотра (и печати).
Начните с этого, и о вас заговорят. Расскажут друзьям и коллегам по работе. А может, они скажут что-то вроде: "Эй, взгляни-ка на это. Вот это стало видно, когда я распечатал страницу. Это ж что-то особенное! Пойду-ка посмотрю, есть ли такая фишка на других страницах их сайта".
Благодаря этой методике, вы внесёте в вашу работу уникальные инновации, полезные вашим пользователям. Конечно, вы не обязаны использовать для этого лишь CSS. Для этих целей подойдёт любая технология, способная различать типы медиа-устройств. Однако самый простой путь - применение CSS. С учётом контекста.
Список литературы
Для подготовки данной работы были использованы материалы с сайта http://infolio.asf.ru/
|
|
Без заголовка |
|
|
CSS |
Обычный HTML позволяет задавать цвет и размер текста с помощью тегов форматирования. Если понадобится изменить параметры однотипных элементов на сайте, придется просматривать все страницы, чтобы найти и поменять теги.
Каскадные таблицы стилей (Cascading Style Sheets, CSS) позволяют хранить цвет, размеры текста и другие параметры в стилях. Стилем называется набор правил форматирования, который применяется к элементу документа, чтобы быстро изменить его внешний вид.
Стили позволяют одним действием применить сразу всю группу атрибутов форматирования. С их помощью можно, например, изменить вид всех заголовков. Вместо форматирования заголовка в три приема, когда сначала задается его размер, затем шрифт "Arial" и, наконец, выравнивание по центру, то же самое можно сделать одновременно, применив стиль к тегу <H1>. Если требуется быстро изменить внешний вид текста, созданного с помощью одного из стилей, достаточно изменить параметры стиля во всех документах, где он используется, и вид текста поменяется автоматически.
Другое преимущество CSS состоит в том, что стили предлагают намного больше возможностей для форматирования, нежели простой HTML. Кроме того, стили могут храниться во внешнем файле, браузер кэширует такие документы, поэтому загрузка сайта будет происходить чуть быстрее.
CSS представляют собой мощную систему для разработчиков сайтов, расширяя их возможности по дизайну и верстке веб-страниц. В научной среде, откуда пошла родом технология WWW, люди были больше заняты содержанием документов, чем их оформлением, однако для большинства людей представление сайта, то, как он выглядит, играет более важную роль. Ограничения HTML породили множество техник создания веб-страниц, таких как:
Эти техники значительно увеличивают сложность разработки веб-страниц, предлагают ограниченную гибкость в их создании и управлении, а также создают трудности для людей ими не владеющими.
Стили решают эти проблемы, в то же время заменяя лишь ограниченную область механизмов представления HTML.
Таблицы стилей могут быть добавлены на веб-страницу тремя разными способами, которые различаются по своим возможностям.
Самый мощный и удобный способ определения стилей и правил для сайта. Стили хранятся в отдельном файле, который может быть использован для любых веб-страниц. Для подключения таблицы связанных стилей используется тег <LINK> в заголовке страницы (пример 1).
Пример 1. Подключение таблицы связанных стилей
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<link rel="stylesheet" type="text/css" href="mysite.css">
или
<link rel="stylesheet" type="text/css" href="http://www.mysite.ru/main.css">
</head>
<body>
<h1>Hello, world!</h1>
</body>
</html>
Путь к файлу со стилями может быть как относительным, так и абсолютным, как показано в данном примере.
Стиль определяется в самом документе и обычно располагается в заголовке веб-страницы. По своей гибкости и возможностям этот способ использования стиля уступает предыдущему, но также позволяет размещать все стили в одном месте. В данном случае, прямо в теле документа. Определение стиля задается тегом <STYLE> (пример 2).
Пример 2. Использование таблицы глобальных стилей
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
H1 {
font-size: 120%; /* Размер шрифта */
font-family: Verdana, Arial, Helvetica, sans-serif; /* Семейство шрифта */
color: #336 /* Цвет текста */
}
</style>
</head>
<body>
<H1>Hello, world!</H1>
</body>
</html>
В данном примере показано изменение стиля заголовка <H1>. На веб-странице теперь достаточно указать только этот тег и стили будут добавлены к нему автоматически.
Внутренний стиль являются по существу расширением для одиночного тега используемого на веб-странице. Для определения стиля используется параметр style, а его атрибуты указываются с помощью языка таблицы стилей (пример 3)..
Пример 3. Использование внутренних стилей
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<H1 style="font-size: 120%; font-family: Verdana, Arial, Helvetica, sans-serif; color: #336">Hello, world!</H1>
</body>
</html>
Рекомендуется использовать внутренний стиль для одиночных тегов или отказаться от его использования вообще, поскольку изменение ряда элементов становится проблематичным. Внутренние стили не соответствуют идеологии структурного документа, когда содержимое и его оформление разделены.
Все описанные методы использования CSS могут применяться как самостоятельно, так и в сочетании друг с другом. В этом случае необходимо помнить об их иерархии. Первым всегда применяется внутренний стиль, затем таблица глобальных стилей и в последнюю очередь таблица связанных стилей. В примере 4 используются сразу два метода добавления таблиц стилей в документ.
Пример 4. Сочетание разных методов подключения стилей
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
H1 { font-size: 120%; font-family: Arial, Helvetica, sans-serif; color: green; }
</style>
</head>
<body>
<H1 style="font-size: 36px; font-family: Times, serif; color: red;">Hello, world!</H1>
<H1>Hello, world!</H1>
</body>
</html>
В приведенном примере первый заголовок задается красным цветом размером 36 пикселов, а следующий — зеленым цветом и другим шрифтом.
С помощью CSS можно определять стиль и вид текста. Аналогично тому, что используется тег <FONT>, задающий свойства шрифта, но стили обладают большими возможностями и позволяют сократить код HTML.
Изменение начертания шрифта и его размера происходит через свойства CSS, которые описаны в табл. 1.
|
Табл. 1. Атрибуты CSS для управления шрифтами |
|||
|
Свойство |
Значение |
Описание |
Пример |
|
font-family |
имя шрифта |
Задает список шрифтов |
P {font-family: Arial, serif} |
|
font-style |
normal |
Нормальный шрифт |
P {font-style: italic} |
|
font-variant |
normal |
Капитель |
P {font-variant: small-caps} |
|
font-weight |
normal |
Нормальная жирность |
P {font-weight: bold} |
|
font-size |
normal |
нормальный размер |
font-size: normal |
Замечание
Когда размер шрифта задается абсолютными значениями, т.е. указывается конкретное значение шрифта в пунктах или пикселах, то изменить эту величину с помощью опции браузера Вид | Размер шрифта невозможно. Если шрифт установлен слишком мелким, то исправить этот недостаток читателю простыми средствами не представляется возможным.
В примере 1 показано использование параметров при работе со шрифтами.
Пример 1. Задание свойств шрифта с помощью CSS
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
H1 { font-family: Arial, Helvetica, Verdana, sans-serif; font-size: 150%; font-weight: light }
</style>
</head>
<body>
<H1>Заголовок</H1>
<p>Обычный текст</p>
</body>
</html>
Ниже приведен результат данного примера.
Заголовок
Обычный текст
В табл. 2 приведены некоторые стилевые параметры для работы с текстом и результат их применения.
|
Табл. 2. Результат использования различных параметров шрифтов |
||||
|
Пример |
Пример |
Пример |
Пример |
Пример |
|
font-family: Verdana, sans-serif; font-size: 120%; font-weight: light |
font-size: large; font-weight: bold |
font-family: Arial, sans-serif; font-size: x-small; font-weight: bold |
font-variant: small-caps |
font-style: italic; font-weight: bold |
Кроме изменения параметров шрифтов, можно управлять и свойствами всего текста. Значения свойств приведены в табл. 3.
|
Табл. 3. Свойства CSS для управления видом текста |
|||
|
Свойство |
Значение |
Описание |
Пример |
|
line-height |
normal |
Интерлиньяж (межстрочный интервал) |
line-height: normal |
|
text-decoration |
none |
Убрать все оформление |
text-decoration: none |
|
text-transform |
none |
Убрать все эффекты |
text-transform: capitalize |
|
text-align |
left |
Выравнивание текста |
text-align: justify |
|
text-indent |
точно |
Отступ первой строки |
text-indent:15px; |
Ниже, в табл. 4 приведены некоторые параметры текста и результат их применения.
|
Табл. 4. Результат использования различных параметров текста |
||||
|
Пример: и это все о нем |
Пример: текст по центру |
Пример: Это не ссылка, а просто текст |
Пример: отступ первой строки |
Пример: полуторный межстрочный интервал |
|
text-transform: capitalize |
text-align:center |
text-decoration: underline |
text-indent: 20px |
line-height: 1.5 |
CSS имеет несколько опций для определения цвета текста и фоновых областей на веб-странице. Эти опции по работе с цветом не только заменяют аналогичные в простом HTML, но и дают массу новых возможностей. Например, традиционный путь для создания цветной области, заключается в применении таблицы. Стили позволяют отказаться от подобного использования таблиц предлагая более простые и удобные варианты управления цветом.
В табл. 1 перечислены свойства элементов, предназначенных для задания цвета.
|
Табл. 1. Управление цветом фона и текста |
|||
|
Свойство |
Значение |
Описание |
Пример |
|
color |
Цвет |
Устанавливает цвет текста |
P { color: #330000 } |
|
background-color |
Цвет |
Цвет фона |
BODY { background-color: #6699FF } |
|
background-image |
URL |
Фоновый рисунок |
BODY { background-image: url (bg.gif) } |
|
background-repeat |
repeat |
Повторяемость фонового рисунка |
BODY { background-image: url (bg.gif) background-repeat: repeat-y } |
|
background-attachment |
scroll |
Прокручиваемость фона вместе с документом |
BODY { background-image: url (bg.gif) background-attachment: fixed } |
|
background-position |
Проценты |
Начальное положение фонового рисунка |
BODY { background-position: left top } |
Цвет, используя CSS, можно задавать тремя способами.
Браузеры поддерживают некоторые цвета по их названию (пример 1).
Пример 1. Установка цвета элемента по его названию
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
P { color: navy; background-color: yellow }
</style>
</head>
<body>
<p>Lorem ipsum dolor sit amet...</p>
</body>
</html>
Цвет можно устанавливать по его шестнадцатеричному значению, как и в обычном HTML (пример 2).
Пример 2. Установка цвета элемента по шестнадцатеричному значению
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
H1 { color: #fc0 }
P { color: #F9E71A; background-color: #98560F }
</style>
</head>
<body>
<h1>Lorem ipsum</h1>
<p>Lorem ipsum dolor sit amet...</p>
</body>
</html>
Также допустимо использовать сокращенную запись, вроде #fc0. Она означает, что каждый символ дублируется, в итоге получим #ffcc00.
Можно определить цвет используя значения красной, зеленой и синей составляющей в десятичном исчислении. Значение каждого из трех цветов может принимать значения от 0 до 255. Также можно задавать цвет в процентном отношении (пример 3).
Пример 3. Установка цвета элемента по шестнадцатеричному значению
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
P { color: RGB(249, 231, 16); background-color: RGB(85%, 24%, 5%) }
</style>
</head>
<body>
<p>Lorem ipsum dolor sit amet...</p>
</body>
</html>
Цвет фона определяется значением параметра background-color, а изображение, которое используется в качестве фона, задается параметром background-image. Значением по умолчанию для цвета фона является transparent, который устанавливает прозрачный фон. Для установки фонового рисунка используется абсолютный или относительный адрес к файлу. Рекомендуется задавать одновременно фоновый рисунок и цвет фона, который будет использоваться в случае недоступности файла изображения.
Пример 4. Цвет фона и фоновое изображение
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
BODY {
background-color: #98560F; /* Цвет фона */
background-image: url('/images/bg.gif') /* Путь к фоновому рисунку */
}
</style>
</head>
<body>
<p>Lorem ipsum dolor sit amet...</p>
</body>
</html>
Если задано фоновое изображение, то свойство background-repeat определяет его повторяемость и способ, как это делать. Допустимыми значениями являются repeat (повторяемость по вертикали и горизонтали), repeat-x (по горизонтали), repeat-y (по вертикали) и no-repeat (только один рисунок, без повторения), как показано в примере 5.
Пример 5. Повторяемость фонового рисунка
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
BODY {
background-image: url('/images/bg.gif'); /* Путь к фоновому рисунку */
background-repeat: repeat-y /* Повторение фона по вертикали */
}
</style>
</head>
<body>
<p>Lorem ipsum dolor sit amet...</p>
</body>
</html>
В данном примере фоновый рисунок повторяется по вертикали.
Положение фона определяется параметром background-position. У него два значения, положение по горизонтали (может быть — right, left, center) и вертикали (может быть — top, bottom, center). Положение можно, также, задавать в процентах, пикселах или других абсолютных единицах (пример 6).
Пример 6. Положение фона
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
BODY {
background-attachment: fixed; /* Фиксируем фон */
background-image: url('mybg.gif'); /* Путь к фоновому рисунку */
background-repeat: no-repeat; /* Отменяем повторение фона */
background-position: right bottom /* Положение фона */
}
</style>
</head>
<body>
<p>Lorem ipsum dolor sit amet...</p>
</body>
</html>
В данном примере фон будет помещен в правый нижний угол страницы. Если нужно определить рисунок в левом верхнем углу, то надо задать следующий вид: background-position: left top.
Параметр background-attachment: fixed фиксирует фон, чтобы он оставался неподвижным при прокрутке содержимого окна браузера.
Для управления видом различных ссылок в CSS используются псевдоклассы, которые указываются после селектора A через двоеточие. В табл. 1 приведены допустимые псевдоклассы и их описания.
|
Табл. 1. Псевдоклассы при работе со ссылками |
|
|
Свойство |
Описание |
|
A:link |
Определяет стиль для обычной непосещенной ссылки. |
|
A:visited |
Определяет стиль для посещенной ссылки. |
|
A:active |
Определяет стиль для активной ссылки. Активной ссылка становится при нажатии на нее. |
|
A:hover |
Определяет стиль для ссылки при наведении на нее мышью. |
Обычно использование псевдокласса link имеет тот же эффект, что и применение стиля к селектору A. Поэтому этот псевдокласс можно опустить.
Одно из наиболее популярных применений CSS — это скрытие подчеркивания у ссылок. С позиции юзабилити не совсем верное решение, поскольку пользователь может сразу не догадаться, что текст, который он видит, является ссылкой. Все ведь уже привыкли — раз подчеркивание используется, значит это ссылка. Но при правильном применении отсутствие подчеркивания у ссылок может придать определенный эффект сайту. Часто делается, что при наведении курсора, ссылка становится подчеркнутой, меняет свой цвет или используется и тот и другой эффект одновременно (пример 1).
Пример 1. Подчеркивание у ссылки и изменение ее цвета
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
A:link {
text-decoration: none /* Убирает подчеркивание для ссылок */
}
A:visited { text-decoration: none }
A:active { text-decoration: none }
A:hover {
text-decoration: underline; /* Делает ссылку подчеркнутой при наведении на нее курсора */
color: red /* Цвет ссылки */
}
</style>
</head>
<body>
...
</body>
</html>
Ниже приведено использование данного примера. При наведении курсора на ссылку, она становится подчеркнутой и красной.
НАВЕДИ СЮДА КУРСОР, УВИДИШЬ РЕЗУЛЬТАТ
Еще один пример демонстрирует использование в ссылках подчеркивания и надчеркивания одновременно. При этом эффекте тонкие линии будут появляться над и под ссылкой при наведении на нее курсора. Это достигается применением параметра text-decoration: underline overline в селекторе A:hover.
Пример 2. Использование подчеркивания в ссылках
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
A:link { text-decoration: none }
A:visited { text-decoration: none }
A:active { text-decoration: none }
A:hover {
text-decoration: underline overline; /* Ссылка подчеркнутая и надчеркнутая */
color: red /* Цвет ссылки */
}
</style>
</head>
<body>
...
</body>
</html>
Результат данного примера показан ниже.
НАВЕДИ СЮДА КУРСОР, УВИДИШЬ РЕЗУЛЬТАТ
Пример 3 показывает, как изменять размер ссылки при наведении на нее курсора.
Пример 3. Изменение размера ссылки
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
A:link { text-decoration: none }
A:visited { text-decoration: none }
A:active { text-decoration: none }
A:hover {
font-size: 24px; /* Размер шрифта */
font-weight: bold; /* Жирное начертание */
color: red /* Цвет ссылки */
}
</style>
</head>
<body>
...
</body>
</html>
Результат данного примера показан ниже.
НАВЕДИ СЮДА КУРСОР, УВИДИШЬ РЕЗУЛЬТАТ
Со ссылками, при помощи CSS, можно сделать интересную особенность. Цвет ссылки, при наведении на нее курсора мыши, остается неизменным, но зато у нее появляется подчеркивание другого цвета, нежели сама ссылка (пример 4). Учтите, что данный прием не работает в некоторых браузерах.
Пример 4. Создание подчеркивание другого цвета
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
A:link { color: blue; text-decoration: none }
A:hover { color: red; text-decoration: underline }
.link { color: blue }
</style>
</head>
<body>
<a href="link1.html"><span class="link">Ссылка</span></a>
</body>
</html>
Результат данного примера показан ниже.
НАВЕДИ СЮДА КУРСОР, УВИДИШЬ РЕЗУЛЬТАТ
Часто возникает необходимость на одной странице использовать ссылки разных цветов и размеров. И применять для каждой области веб-страницы ссылки подходящего типа. Одни для меню, другие для текста. В этом случае создаем два или больше класса со своими параметрами и применяем их по своему усмотрению. В примере 6 достаточно поменять значения у соответствующего класса, и цвета у ссылок, где этот класс используются, изменятся автоматически.
Пример 5. Ссылки разных цветов
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
A { font-size: 14px; color: red }
A.link1 { font-size: 12px; color: green }
A.link2 { font-size: 14px; color: blue }
</style>
</head>
<body link="#0000ff">
<p><a href="link1.html">Ссылка 1</a></p>
<p><a href="link2.html" class="link1">Ссылка 2</a></p>
<p><a href="link3.html" class="link2">Ссылка 3</a></p>
</body>
</html>
Результат данного примера показан ниже.
| Ссылка 1 | Ссылка 2 | Ссылка 3 |
С помощью CSS можно создать маркированные и нумерованные списки, а также использовать в качестве маркера подходящее изображение.
В табл. 1 перечислены свойства элементов, предназначенных для создания и изменения списков.
|
Табл. 1. Свойства CSS для управления видом списка |
|||
|
Свойство |
Значение |
Описание |
Пример |
|
list-style |
disc |
Вид маркера. Первые три используются для создания маркированного списка, а остальные — для нумерованного. |
LI {list-style: circle} |
|
list-style-image |
none |
Устанавливает символом маркера любую картинку. |
LI {list-style-image: url(check.gif)} |
|
list-style- position |
outside |
Выбор положения маркера относительно блока строк текста. |
LI {list-style-position: inside} |
Поскольку тег <LI> наследует стилевые свойства тега <OL> или <UL>, который выступает в качестве его родителя, то можно устанавливать стиль как для селектора UL, так и для селектора LI. Так, в примере 1 используется селектор UL, для него и задаются стилевые параметры.
Пример 1. Создание маркированного списка
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
UL {
list-style: square; /* Маркеры в виде квадрата */
list-style-position: outside; /* Маркеры размещаются за пределами текстового блока */
color: navy /* Цвет текста списка */
}
</style>
</head>
<body>
<ul>
<li>Заголовок должен быть короче трех строк.</li>
<li>При названии разделов используйте уже устоявшиеся термины, такие как гостевая книга, чат, ссылка, главная страница и другие.</li>
<li>Перед использованием специального термина или слова, решите, будет ли оно понятно читателю.</li>
<ul>
</body>
</html>
В данном примере используются квадратные маркеры и их внешнее размещение относительно текста. Цвет — темно-синий.
Чтобы установить свое собственное изображение в качестве маркера применяется параметр list-style-image, как показано в примере 2.
Пример 2. Использование изображений в качестве маркера
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
LI {
list-style-image: url('images/check.gif') /* Путь к файлу с маркером */
}
</style>
</head>
<body>
<ul>
<li>Заголовок должен быть короче трех строк.</li>
<li>При названии разделов используйте уже устоявшиеся термины, такие как гостевая книга, чат, ссылка, главная страница и другие.</li>
<li>Перед использованием специального термина или слова, решите, будет ли оно понятно читателю.</li>
<ul>
</body>
</html>
Результат данного примера показан ниже. В качестве маркеров используется маленькая картинка.
Некоторые примеры создания различных списков приведен в табл. 2.
|
Табл. 2. Возможные виды списков |
||||||||||||||||||
|
Код HTML |
Пример |
|||||||||||||||||
|
<li style="list-style: disc"> |
Что следует учитывать при тестировании сайта:
|
|||||||||||||||||
|
<li style="list-style: circle"> |
Что следует учитывать при тестировании сайта:
|
|||||||||||||||||
|
<li style="list-style: square"> |
Что следует учитывать при тестировании сайта:
|
|||||||||||||||||
|
<li style="list-style: decimal"> |
Нумерованный список с арабскими цифрами:
|
|||||||||||||||||
|
<li style="list-style: lower-roman&quo
Процитировано 5 раз
Сегодня обязательно выпью бутылкуКлинского светлого и выкурю пачку сигарет так как ЛОМКА побеждат
За день всего две сигареты и ниодного глотка пива))))))))
Часть 1ВведениеRuby представляет собой объектно-ориентированный язык программирования интерпретирующего типа. Он был создан программистом из Японии -- Юкихиро Матсумото (Yukihiro Matsumoto), где этот язык пользуется большей популярностью нежели Python или Perl! Первая часть из серии является введением в основы языка Ruby. Более глубокий материал будет даваться в последующих частях. Я не собираюсь превозносить язык Ruby и доказывать его преимущества перед другими языками программирования. Большинство из нас прекрасно понимают, что каждый язык программирования имеет свои неповторимые черты. И ваш выбор скорее будет зависеть от ваших личных предпочтений и доступности стандартных библиотек, нежели от неких таинственных технических проблем. ТребованияЯ полагаю, что вы работаете в Linux и Ruby уже установлен у вас. Ruby - это свободно распространяемое программное обеспечение и поэтому нет никаких препятствий, ограничивающих его использование. Вы можете скачать его с домашней странички проекта Ruby Hello WorldНачнем с обычной в таких случаях программы `Hello, World' % cat > hello.rb print "Hello World\n" ^D % ruby hello.rb Hello World % ПеременныеИмена переменных должны начинаться с символа: $ глобальная переменная @ переменная экземпляра (поле объекта, данные-член) a-z или '_' локальная переменная A-Z константа Кроме того существуют еще две псевдопеременные, которые являются исключением из вышеуказанного правила - это `self' и `nil'.
Обе они именуются как локальные переменные, но таковыми не являются! Реальный смысл этих переменных станет вам понятен немного позже. Глобальные переменныеИмена глобальных переменных должны начинаться с символа `$'. Глобальные переменные доступны из любой части программы. Следует отметить, что неинициализированная глобальная переменная имеет значение 'nil'. Этот факт демонстрирует следующий пример: % ruby
print $foo,"\n" $foo = 5 print $foo,"\n" ^D % Результат работы интерпретатора: nil 5 Эта особенность дает возможность `связывать' процедуры с глобальными переменными, т.е. при изменении значения переменной `связанная' процедура будет вызываться автоматически. Но об этом позже! Существует ряд специальных предопределенных глобальных переменных, являющихся по сути системными переменными интерпретатора Ruby (доступны только для чтения). Некоторые из них приведены ниже.
Локальные переменныеИмена локальных переменных должны начинаться с прописных (маленьких) символов латинского алфавита или с символа '_'. В отличие от глобальных переменных и ссылок на переменные, локальные переменные не принимают значение 'nil', например, при выполнении следующего кода: % ruby print foo ^D Вы получите сообщение об ошибке: "undefined local variable or method 'foo' for #(object...)".
Область видимости локальных переменных ограничивается одной из следующих разновидностей блоков программы
Локальная переменная, инициализированная в каком либо блоке (или процедуре), после выхода за пределы блока становится неопределенной. Например: def foo(n) k = 2 * n
print "\n",k,"\n"
print defined? k,"\n"
end foo 3 print defined? k,"\n" ^D Вывод интерпретатора:
6 local-variable nil В этом примере оператор `defined?' используется для проверки существования передаваемого ему аргумента. Результаты работы оператора "local-variable" и "nil" понятны и так и в комментариях не нуждаются. КонстантыИмена констант начинаются с заглавных (больших) символов латинского алфавита. Но, как правило, программирующие на Ruby, дают константам имена, состоящие только из заглавных символов. Так, например и 'Foo', и 'FOO' являются константами. Как и в случае с локальными переменными, константы инициализируются оператором присваивания, а обращение к неинициализированной константе, равно как и попытка изменения инициализированной константы, вызывает сообщение об ошибке. Проверьте это самостоятельно. СтрокиСтроки в Ruby ограничиваются либо одинарными ('...'), либо двойными кавычками ("..."). Однако такие строки имеют различия между собой. При использовании двойных кавычек допускается вставлять в строки управляющие escape-последовательности, начинающиеся с символа '', а также вычислять выражения с помощью конструкции #{}. Например: print "\n" print '\n' print "\001","\n" print '\001',"\n" print "abcd #{5*3} efg","\n"
var = " abc " print "1234#{var}567","\n"
^D \n \001 abcd 15 efg 1234abc567 Дополнительную информацию по строкам вы получите в разделе, посвященном массивам, поскольку массивы и строки во многом похожи друг на друга. МассивыДля определения массивов используются квадратные скобки '[]'. Массивы в Ruby являются гетерогенными (т.е. могут содержать данные различных типов). a = [1,2,"3"] print a,"\n" ^D 123 Однако, если вы попытаетесь заставить интерпретатор подсчитать сумму элементов массива, показанного выше, то он выдаст сообщение об ошибке: Error!!String cannot be coerced into Fixnum
Дело в том, что элемент массива `3' хранится в виде строки. Если вычисление суммы элементов массива задать следующим образом: a = [1,2,"3"] b = a[0] + a[1] + a[2].to_i print b,"\n" ^D 6 То интерпретатор выполнит его без ошибки. Добавление '.to_i' к 3-му элементу массива (т.е. a[2].to_i) заставляет интерпретатор выполнить преобразование содержимого элемента массива a[2] в целое со знаком. Ради эксперимента можете попробовать подставить '.to_s'. К массивам можно применять операции конкатенации (слияния) и повторения. a = [1,2,"3"] print a + ["foo","bar"] print a * 2 ^D Результат 123foobar 123123 Можно получить "срез" массива: a = [1,2,"3","foo","bar"] print a[0],"\n" print a[0,2],"\n" print a[0..3],"\n" print a[-2..2],"\n" print a[-3..-1],"\n" Массивы и строки взаимно конвертируемы. Массив можно преобразовать в строку с помощью метода 'join', а строку -- в массив с помощью метода 'split'. a = [1,2,3] print a[2],"\n" a = a.join(":")
print a[2],"\n" print a,"\n" a = a.split(":")
print a[2],"\n" print a,"\n" ^D Ассоциативные массивы (хэши (англ. hash) или словари)-- еще один немаловажный вид представления данных. Хэши содержат пары ``ключ'' и ``значение'', см. пример ниже: h = {1 => 2, "2" => "4"}
print hash,"\n" print hash[1],"\n" print hash["2"],"\n" print hash[5],"\n" ^D Я, надеюсь, результаты убедительны! Управляющие конструкцииIf - elseПопробуем написать функцию вычисления факториала. Математическое определение факториала: n! = 1 (если n==0) n! = n * (n-1)! (иначе)
На Ruby вычисление факториала может быть реализовано следующим образом: def fact(n) if n == 0
1
else
n * fact(n-1)
end
end print fact 4,"\n" В результате получится 24. Из-за наличия ключевого слова `end' Ruby иногда называют 'Алголо-подобным' языком. В данном примере рекурсивной функции вы можете заметить отсутствие оператора возврата результата (return). Естественно, использование этого оператора не возбраняется, но в данной ситуации он является излишним, поскольку в качестве возвращаемого значения принимается результат вычисления последнего выражения. Цикл forfor i in 0..4 body-of-for
end Где i -- переменная цикла, а 0..4 -- диапазон значений. Для строковых переменных, заголовок цикла for можно записать так: for i in "abc" Цикл whileПопробуйте запустить этот пример i=0 while i < 10 print i+=1,"\n"
end CaseОператор выбора case используется для проверки набора условий. В результате работы следующего примера i = 7 case i when 2..5 print "i in 2 to 5\n"
when 6..10 print "i in 6 to 10\n"
end ^D вы получите i in 6 to 10 2..5 -- означает диапазон значений от 2 до 5 включительно. Здесь проверяется - попадает ли значение переменной i в заданный диапазон. В случае строк, оператор case будет выглядеть примерно так: case 'abcdef' when 'aaa','bbb' print 'contains aaa or bbb \n"
when /def/ print "contains def \n"
end ^D contains def Обратите внимание на слэши (символ "/"), которые окружают ключевое слово "def". Они используются для задания границ регулярного выражения, которые мы рассмотрим позднее. Дополнительные управляющие конструкцииОператор case, из примера, приведенного выше, проверяет попадание значения переменной i в диапазон 2..5. Эта же проверка может быть записана несколько иначе, например: (2..5) === i Оператор отношения '===' используется для проверки выполнения нескольких условий одновременно и интерпретируется подобно ключевому слову when. Попробуйте самостоятельно реализовать функцию, подобную isalnum(),isalpha(),isnum() и т.п. с помощью оператора '===' внутри конструкции if. При использовании конструкций if и while для проверки отдельных значений, код может быть несколько сокращен i = 7 print "contained in 5..10\n" if (5..10) === i print i-=1,"\n" while i > 0 ^D contained in 5..10 6 5 4 3 2 1 0 Иногда может возникнуть необходимость в инвертировании проверяемого условия. Так, условие "если" (if) при инвертировании приобретает смысл "если не", условие while -- в условие until и т.д. Существует четыре различных варианта управления исполнением цикла. Первый, аналогичный C -- break, означает выход за тело цикла. Второй -- next, переход в начало следующей итерации (аналог continue в C). Третий -- redo, перезапускает текущую итерацию. Следующий C-код иллюстрирует механизм работы этих трех методов (break, next и redo): while(condition) {
label_redo:
goto label_next; /* ruby's "next" */ goto label_break; /* ruby's "break"*/ goto label_redo; /* ruby's "redo" */ ...
...
label_next:
} label_break: ... И четвертый вариант -- оператор return. Фактически, этот оператор приводит не только к прерыванию цикла, но и к завершению работы метода (функции), который содержит прерываемый цикл. ЗаключениеМы рассмотрели некоторые элементарные особенности языка программирования Ruby в том объеме, который позволит вам написать свои первые программы. В своих следующих статьях, посвященных этому "драгоценному камню" (слово Ruby может быть переведено на русский язык как "рубин", прим. перев.), я буду делиться своим опытом , приобретенным при его изучении. До свидания!Часть 2Регулярные выраженияРегулярные выражения в Ruby заключаются между парой символов '/' (слэш), как в Perl или awk. Они поражают своей выразительностью и мощью, когда приходится иметь дело с шаблонами (например, поиск по шаблону). print "abcdef" =~ /de/,"\n" print "aaaaaa" =~ /d/,"\n" ^D 3 nil Где `=~' -- это оператор поиска по шаблону. Он возвращает позицию в строке, где было найдено совпадение с шаблоном, или nil, если поиск не увенчался успехом. Синтаксис регулярных выражений весьма специфичен, взгляните ниже:
[ ] диапазон. (т.е., запись [a-z] означает любой символ в диапазоне от a до z) \w буква или цифра. то же самое, что и [0-9A-Za-z_] \W символ, не являющийся ни буквой ни цифрой \s пробел. то же самое, что и [ \t\n\r\f] \S не пробельный символ. \d цифра. то же самое, что и [0-9]. \D символ, не являющийся цифрой. \b граница слова. \B не граница слова. * повторяется 0 или большее число раз + повторяется 1 или большее число раз {m,n} повторяется не менее n и не более m раз ? 1 или 0 раз | логическое "или" ( ) группировка Например, выражение `^f[a-z]+' имеет смысл "символ f, за которым следует хотя бы один символ из диапазона от `a' до `z'". А теперь представим, что вам необходимо найти строку, которая подходит под описание, хотя бы такое: "Начинается с прописной буквы f, за которой следует одна заглавная буква и далее, до конца строки, возможно, следуют только прописные буквы". На языке C вам наверняка потребуется написать с дюжину строк, чтобы выполнить такой поиск. Разве я не прав? В Ruby же вы просто проверяете строку на совпадение с шаблоном /^f[A-Z](^[a-z])*$/. Возможность поиска строк по заданному шаблону часто используется в среде UNIX, типичный пример -- `grep'. Познакомимся с регулярными выражениями поближе. Рассмотрим следующую программу: # Сохраните этот код в файле regx.rb
st = "\033[7m" en = "\033[m"
while TRUE
print "str> "
STDOUT.flush
str = gets
break if not str
str.chop!
print "pat> "
STDOUT.flush
re = gets
break if not re
re.chop!
str.gsub! re, "#{st}\\&#{en}"
print str, "\n"
end print "\n" # А теперь дайте команду: ruby regx.rb Программа предложит ввести две строки. Первая -- строка, по которой будет осуществляться поиск, вторая -- регулярное выражение. После чего будет выполнен поиск в строке по шаблону и найденная часть будет подсвечена. Хочу уточнить, что программа использует escape-последовательности для управления параметрами отображения, поэтому корректное отображение результата гарантировано только на ANSI-совместимых терминалах. str>foobar pat>^fo+ foobar ~~~ Для этого примера будут подсвечены первые три символа (foo). Символы ``~~~'' я использовал для выделения найденной подстроки на случай, если вы читаете эту статью с помощью текстового браузера. Давайте немного поэкспериментируем. str>asd987wonew06521 pat>\d asd987wonew06521 ~~~ ~~~~~ str>foozboozer pat>f.*z foozboozer ~~~~~~~~ Обратите внимание на то, что в последнем примере будет выделена подстрока foozbooz, а не fooz. Это потому, что в качестве результата поиска по шаблону принимается самый длинный вариант. Следующий пример на первый взгляд выглядит более сложным: str> Wed Feb 7 08:58:04 JST 1996
pat> [0-9]+:[0-9]+(:[0-9]+)? Wed Feb 7 08:58:04 JST 1996
~~~~~~~~
Теперь попробуем написать шаблон для поиска шестнадцатеричных (HEX) чисел. (например, таких как 0x123af00c или 0xbc13590ae). def chab(s) # "поиск шестнадцатеричного числа, заключенного в угловые скобки"
(s =~ /<0(x|X)(\d|[a-f]|[A-F])+>/) != nil
end print chab "Здесь нет числа." print "\n",chab "Может здесь? {0x35}" # используются не те скобки, которые ожидаются
print "\n",chab "Или здесь? <0x38z7e>" # Это не HEX-число print "\n",chab "Вот оно: <0xfc0004>." print "\n" ^D false false false true ИтераторыПод итератором понимается код (объект), выполняющий некоторую последовательность действий несколько раз. Взгляните на следующий пример, написанный на языке C: char *str; for (str = "abcdefg"; *str != '\0'; str++) {
/* обработка очередного символа */
} Обратите внимание на степень абстракции, которую предоставляет синтаксис цикла for(...). Но не смотря на это программист все равно должен знать внутреннее представления данных, поскольку в данном случае выполнение цикла прекращается при встрече "пустого" (NULL) символа -- завершающего символа для строк. Наличие итераторов - одна из особенностей , которая отличает языки высокого уровня. Взгляните на пример сценария командной оболочки (/bin/sh): for i in *.[ch]; do # ... некоторые действия, выполняемые для каждого файла done Эта конструкция обрабатывает все *.c и *.h файлы в текущем каталоге, причем командная оболочка сама беспокоится о выборе файла с подходящим расширением одного за другим. Разве это не более высокий уровень программирования чем C? Что вы об этом думаете? Для встроенных типов данных создать итератор достаточно просто, но в ООП (Объектно Ориентированное Программирование прим. перев.) это может стать серьезной проблемой, поскольку пользователи могут определять свои собственные типы данных. Для разрешения этой проблемы каждый ООП-язык предлагает свои способы сделать сложное простым, например очень распространен вариант с отдельным классом, управляющим итерацией и т.д.. Ruby позволяет определять управляющие конструкции непосредственно. В терминах Ruby такая управляющая конструкция называется итератором. Взгляните на следующий пример: "abc".each_byte{|c| printf "%c\n", c}
^D a b c Где each_byte является итератором для каждого символа в строке. Локальная переменная `c' служит здесь для приема очередного символа. C-подобный код этого итератора может быть записан так: s="abc" i=0 while i < s.length printf "%c\n",s[i]
i+=1
end ^D a b c ... однако итератор each_byte концептуально более прост и код, использующий итератор, останется работоспособным, даже если реализация класса строк претерпит существенные изменения. Замечательная особенность итераторов -- устойчивость к ошибкам, которые могут возникнуть из-за таких изменений, и я думаю, что это может служить характеристикой хорошего кода. Еще один итератор для строк. "a\nb\nc\n".each_line{|l| print l}
^D a b c Такая утомительная задача, как выделение отдельных элементов строки, разделенных некоторым символом, очень просто решается с помощью итераторов. Попробуем переписать этот пример с помощью оператора for. for l in "a\nb\nc\n" print l
end ^D a b c Оператор for выполняет итерации способом, аналогичным итератору строки. И выполняет те же действия, что и each_line в предыдущем примере Цикл может быть прерван и перезапущен оператором `retry'. См. пример ниже. c = 0 for i in 0..4 print i
if i==2 and c==0
c = 1 print "\n"
retry
end
end ^D 012 01234 Итератору можно передать даже блок исполняемого кода, который может быть исполнен с помощью оператора yield. Ниже показан пример итератора repeat, который выполняет вывод на экран заданное число раз. def repeat(num) while 0 < num
yield
num-=1
end
end repeat(4) {print "hello world\n"}
^D hello world hello world hello world hello world Если вам что-то непонятно -- попробуйте вставить в пример вывод значения переменной num до и после оператора yield. С помощью оператора retry можно попробовать определить while-подобный итератор (см. пример ниже), но на практике такой прием не пользуется популярностью из-за снижения скорости исполнения. def MYWHILE(cond) return if not cond
yield
retry
end i = 0 MYWHILE(i<3) {print i,"\n" ;i+=1}
^D 0 1 2 Надеюсь, что к настоящему моменту у вас сложилось достаточно четкое представление об итераторах. Конечно, существуют некоторые ограничения, но тем не менее, при создании новых типов данных очень удобно включать в их реализацию и соответствующие итераторы. В этом случае примеры итераторов `repeat()' и `MYWHILE()' не представляют особого интереса. К итераторам мы еще вернемся, после того как рассмотрим понятие класса. Объектно-ориентированный образ мышления"Объектно-ориентированный" -- очень броское выражение. Ruby претендует на звание объектно-ориентированного языка программирования, но что же все таки означает понятие "объектно-ориентированный"? Можно дать разные ответы на этот вопрос, но все они, вероятно, сводятся к одному и тому же. Однако, не будем торопиться с выводами и для начала рассмотрим традиционную парадигму программирования. В традиционном представлении проблема программирования заключается в создании структур данных и процедур, обрабатывающих эти данные. В рамках такого представления данные являются "инертными", "пассивными" и "беспомощными" элементами программы, поскольку они полностью отданы на милость процедурам, которые в свою очередь "активны", "логичны" и "всемогущи". Главная проблема такого подхода в том, что программы пишут люди, которые не в состоянии удерживать в памяти все до мельчайших подробностей. По мере развития проекта количество процедур увеличивается, вспоминать что где и как работает становится все труднее и труднее. Повышается вероятность появления опечаток, приводящих к трудноуловимым ошибкам. "Всплывают" сложные и непредсказуемые взаимодействия. Работа по управлению таким проектом начинает напоминать попытку пронести рассерженного кальмара мимо лица не дав ему коснуться своими щупальцами. Существуют определенные рекомендации по уменьшению этих отрицательных моментов, но есть лучшее решение, представляющее собой совершенно иной подход к программированию. При объектно-ориентированном подходе значительная часть действий делегируется самим данным, таким образом понятие "данные" можно перевести из разряда "пассивных" элементов программы в разряд "активных". Или другими словами
Воспринимая классы как "механизмы" ("машины"), мы ничего не можем сказать об их внутреннем устройстве, которое может быть очень простым или наоборот очень сложным. Всю работу мы выполняем "щелкая переключателями" и "читая показания приборов". Мы позволяем себе "вскрывать" их только в исключительных случаях -- когда абсолютно уверены в необходимости что-то подправить. После того как "машина" будет готова, мы можем смело забыть о том как она работает Вам может показаться, что мы делаем лишнюю работу, на самом деле мы выполняем работу по предотвращению ошибок. Рассмотрим простой пример из реальной жизни, но тем не менее прекрасно иллюстрирующий некоторые понятия. В моем автомобиле имеется одометр, измеряющий расстояние, пройденное с момента последнего нажатия на кнопку сброса. Как можно представить себе модель этого прибора на языке программирования? На языке C его можно представить как переменную, возможно типа float. Управляющая программа должна увеличивать эту переменную на некую величину и обнулять ее, когда это необходимо. Что тут может быть неправильно? В программе может крыться ошибка, в результате которой, значение переменной будет меняться непредсказуемым образом. Кто писал на C -- тот знает, что на поиски таких ошибок уходит масса времени. А когда причина обнаруживается, то она может оказаться простой до нелепости. (Такие моменты обычно сопровождаются звонким хлопком по лбу!) При объектно-ориентированном подходе та же проблема решается несколько иначе. Программист уже не задается вопросом: "Какой из имеющихся типов данных более подходит для решения задачи?". Его скорее интересует вопрос: "Как работает моделируемый объект?". Т.е. подход совершенно иной. При таком подходе нам необходимо потратить немного времени для того чтобы решить -- что такое одометр и как он взаимодействует с окружающим миром. Пусть в нашем представлении это будет небольшой механизм, который способен измерять и отображать пройденное расстояние, обнулять его и ничего больше. Мы не предусматриваем возможность занесения в прибор произвольного значения. Почему? Потому, что это расстояние фактически не было пройдено и мы это прекрасно понимаем. Функциональность прибора мы уже описали выше и это описание предусматривает все, что нам нужно. Поэтому, сразу же предусмотрим выдачу сообщения об ошибке, если где-то в программе будет сделана попытка записать в одометр "левое" значение (скажем -- задание температуры для установки климат-контроля салона), во время выполнения программы (или на этапе компиляции, это зависит от типа используемого языка программирования) о том, что не допустимо заносить в одометр произвольные значения. Сообщение не обязательно должно быть очень подробным, но достаточным для того, чтобы понять в чем дело. Конечно -- это не устраняет самой ошибки, но дает возможность быстро локализовать ее. Это один способ из множества, с помощью которого объектно-ориентированное программирование позволяет сэкономить время, затрачиваемое на поиск ошибок. Поднявшись на более высокий уровень абстракции, можно сказать, что нам нужен не один конкретный прибор, а скорее фабрика по их производству, потому что создать такую фабрику так же просто, как и отдельно взятый прибор. Фабрика выпускает приборы имея единственный шаблон. Такой шаблон называется классом, а сам прибор -- объектом. Большинство объектно-ориентированных языков программирования требуют, чтобы определение класса предшествовало созданию и использованию объектов этого класса, но в Ruby это не так. Особо хочу подчеркнуть, что использование объектно-ориентированного языка не вынуждает следовать объектно-ориентированному стилю программирования. На любом языке можно написать запутанный, сырой, плохо продуманный, неустойчивый, содержащий ошибки код. Язык Ruby (в противоположность другим, особенно C++) делает объектно-ориентированный стиль программирования естественной привычкой так, что даже когда вам приходится работать над маленькими проектами, у вас не возникает потребности писать уродливый код, чтобы сэкономить усилия. Следующей нашей темой будут "органы управления" (методы объектов), а затем мы перейдем к "фабрикам" (классам). Оставайтесь с нами! Третья частьМетодыМетод -- это некоторая функция, описывающая реакцию объекта на поступивший запрос. Взгляните на пример вызова метода, приведенный ниже: print "asdfgh".length ^D 6 Из примера видно, что для строкового объекта вызывается метод с именем `length'. Немного усложним: foo = "abc" print foo.length,"\n" foo = [1, 2] print foo.length,"\n" ^D 3 2 Из этого примера видно, что решение о том какой метод вызвать принимается во время исполнения и, что выбор этот зависит от содержимого переменной. (в первом случае переменная foo представляется как строковая переменная, во втором -- как массив прим. перев.). У читателя может возникнуть вопрос: "Как же так? Ведь длина строки и длина массива считаются по разному?". Не стоит беспокоиться. К счастью, Ruby автоматически выбирает соответствующий ситуации метод. Эта особенность в объектно-ориентированном программировании называется полиморфизмом. Нет никакой необходимости знать о том как работает тот или иной метод, но каждый должен знать о том какие методы имеются у объекта. При вызове неизвестного объекту метода, возникает ошибка. Например, попробуйте вызвать метод "length"для объекта "foo", присвоив ему предварительно значение "5". Я уже упоминал о специальной псевдопеременной self. Она определяет объект, чей метод был вызван. Однако указание этой переменной очень часто опускается, например: self.method_name(arguments...) может быть сокращено до method_name(arguments...) Эти два вызова идентичны друг другу, просто второй способ является сокращенным вариантом первого. КлассыРеальный мир состоит из объектов, которые могут быть классифицированы. Например, годовалый малыш, увидев собаку, думает о ней как "гав-гав". В терминах объектно-ориентированного программирования, "гав-гав" -- это класс, а объект, принадлежащий классу -- экземпляр класса. В Ruby, как и в других объектно-ориентированных языках программирования, сперва определяется класс, чтобы описать поведение объекта, а затем создается экземпляр класса -- отдельный объект. А теперь давайте определим класс. class Dog def bark
print "Гав гав\n"
end
end ^D Описание класса должно начинаться с ключевого слова class и заканчиваться ключевым словом end. Ключевое слово def в данном контексте начинает определение метода класса. Итак, мы описали класс с именем `Dog', а теперь создадим объект. tommy = Dog.new tommy.bark ^D Гав гав Этот код создает новый экземпляр класса Dog и связывает его с переменной tommy. Метод `new' любого класса создает новый экземпляр этого класса. Теперь переменная tommy обладает свойствами класса Dog и может "прогавкать" (метод `bark'). НаследованиеВы когда нибудь задавались вопросом -- как разные люди классифицируют объекты? Например, как люди видят собаку? Математик может описать собаку как комбинацию чисел и геометрических фигур. Физик -- как результат работы естественных и искусственных сил. Моя сестра (биолог) может представить собаку как разновидность отряда псовых домашних (canine domesticus). Для нее собака -- это разновидность псовых, псовые -- разновидность млекопитающих, а млекопитающие -- всегда животные. Отсюда видно, что классификация объектов имеет форму иерархии, хотя и не всегда. Посмотрим, как это можно реализовать в Ruby. class Animal def breath
print "Вдох и выдох\n"
end
end class Cat<Animal def bark
print "мяу\n"
end
end tama = Cat.new tama.breath tama.bark ^D Вдох и выдох мяу Из примера видно, что класс Cat не имеет определения метода breath (рус. - "дыхание", прим. перев.), но этот метод наследуется от родительского класса Animal. И имеет дополнительный специфичный метод `bark' (рус. - "лаять", здесь следует читать как "звук, издаваемый животным", прим. перев.). Известно, что свойства родительского класса не всегда наследуются потомками. Например, пингвины не могут летать, хотя и являются птицами. Однако пингвины несут в себе многие другие черты, присущие птицам, например, они откладывают яйца. Подобные случаи могут быть реализованы и в Ruby, однако оставляю читателям возможность разобраться с этим самим. При создании нового класса, наследующего черты родительского класса, нам необходимо будет только определить методы, описывающие различия между потомком и родителем. Это одно из достоинств объектно-ориентированного программирования, которое иногда называют "дифференциальным программированием". Переопределение методовМы уже наблюдали различия в поведении экземпляров дочерних классов после переопределения методов родительского класса. Посмотрите на пример ниже: class Human def print_id
print "Я - человек.\n"
end
def train_toll(age)
print "Детский билет.\n" if age < 12
end
end Human.new.print_id class Student1<Human def print_id
print "Я - студент.\n"
end
end Student1.new.print_id class Student2<Human def print_id
super
print "И студент.\n"
end
end Student2.new.print_id ^D Я - человек. Я - студент. Я - человек. И студент. В дочернем классе, переопределяющем метод родительского класса, можно вызвать оригинальный метод родителя с помощью ключевого слова `super'. Попробуйте запустить этот код: class Student3<Human def train_toll(age)
super(11) # принудительно снижаем возраст
end
end Student3.new.train_toll(25) ^D Детский билет. Надеюсь, этих простых примеров достаточно для того, чтобы понять принципы наследования и переопределения методов. Еще о методахВозможность вызова метода может быть ограничена. Для функции (определяемой на верхнем уровне) смотрите ниже: def sqr(x) x * x
end print sqr(5) ^D 25 Если определение функции находится за пределами описания класса, то она добавляется как метод класса Object. Класс Object является базовым для всех остальных классов -- в Ruby все классы являются потомками класса Object. Таким образом, метод `sqr' может вызываться из других классов. Теперь, когда любой класс может вызвать метод `sqr', давайте попробуем вызвать его с помощью псевдопеременной `self': print self.sqr(5) ^D ERR: private method `sqr' called for (Object) Как показано выше, вызов функции с помощью `self' приводит к выдаче сообщения об ошибке. Это сообщение недостаточно понятно (интуитивно), что оно означает? Суть в том, что функции, определенные за пределами какого либо класса должны вызываться как простые функции, а не как методы. Посмотрите какое сообщение об ошибке получается при вызове не определенного метода. Методы, определенные как простые функции, должны вызываться как простые функции, подобно функциям C++, даже в пределах класса. Область видимости метода может быть ограничена ключевыми словами "public" и "private", где public -- определяет общедоступные методы класса, а private -- скрытые, которые могут быть вызваны только из других методов класса. class Test def bar print "bar -< "
foo
end
private
def foo
print "foo\n"
end
end temp = Test.new temp.bar temp.foo ^D bar -< foo ERR: private method `foo' called for (Test) Из этого примера все должно быть понятно. Единичные (Singleton) методыПоведение экземпляра определяется его принадлежностью к тому или иному классу, однако порой возникает необходимость в наделении объекта некоторой, свойственной только ему, индивидуальностью. В большинстве языков программирования вам придется создавать для этого отдельный класс. Ruby же позволяет добавить специфичный метод к конкретному экземпляру (объекту) без лишних телодвижений. class SingletonTest def size
print "25\n"
end
end t1=SingletonTest.new t2=SingletonTest.new def t2.size print "10\n"
end t1.size t2.size ^D 25 10 Где t1 и t2 -- принадлежат одному и тому же классу и тем не менее, для экземпляра t2 переопределяется метод `size', обеспечивая его индивидуальность. Такой специфичный метод называется единичный метод (singleton method). В качестве примера применения единичного метода можно привести кнопки в окне программы с графическим интерфейсом, где каждая кнопка должна выполнять свои действия по нажатии. Мы можем переопределить метод, обрабатывающий нажатие у каждой из имеющихся кнопок. МодулиМодули в Ruby очень похожи на классы, но используются для группировки родственных классов в одном месте. Вот три основных отличия модулей от классов:
Грубо говоря, существуют две основные причины использования модулей. Первая -- собрать методы и константы в одном месте. Например: print Math::PI,"\n" print Math.sqrt(2),"\n" ^D 3.141592654 1.414213562 Оператор `::' указывает на то, что константа определена в соответствующем модуле или классе. Чтобы обращаться к методам или константам напрямую, следует использовать директиву `include' include Math print sqrt(2),"\n" print PI,"\n" ^D 1.414213562 3.141592654 Другая причина -- "смешение" (`mixin') модулей. Смысл этого термина достаточно сложен для понимания, поэтому остановимся на нем подробнее. Некоторые объектно-ориентированные языки допускают наследование от нескольких родительских классов, такая возможность называется множественным наследованием. Ruby преднамеренно лишен этой возможности. Вместо этого он допускает смешение (mixin) с модулем. Как сказано выше, модуль во многом похож на класс. Методы или константы в модуле не могут наследоваться, но могут быть добавлены в другие модули или классы с помощью директивы include. Таким образом, подключение модуля к определению, добавляет (подмешивает) свойства модуля к свойствам класса или модуля. Смешение модулей можно наблюдать в стандартной библиотеке, где в результате "смешения" модулей с классом, имеющим метод `each', возвращающий каждый элемент, последний получает в свое распоряжение методы `sort', `find' и т.п.. Между множественным наследованием и "смешением" существуют следующие отличия:
Эти различия запрещают сложные взаимоотношения между классами, простота ставится во главу угла. По этой причине Ruby не поддерживает множественного наследования. В языках, поддерживающих множественное наследование, вполне может возникнуть ситуация, когда классы имеют несколько предков, а взаимоотношения между экземплярами классов создают запутанную сеть... Ситуация слишком сложна для восприятия человеческим мозгом, по крайней мере -- моим... С другой стороны, смешение представляет все это, просто как "коллекцию специфических свойств из всего, что было добавлено". Даже в языках с множественным наследованием, считается, что лучше расширять классы с использованием смешения, нежели разрабатывать сложные отношения наследования. В Ruby эта идея была продвинута дальше, заменив собой идею множественного наследования. Процедурные объектыПредставьте себе, что вы пишите программу, которая обрабатывает некоторые сигналы. Знакомые с этим поймут всю прелесть передачи процедуры в виде аргумента методу (который занимается обработкой сигналов). Процедурные объекты создаются с помощью встроенного метода proc. Исполняемый код записывается внутри фигурных скобок. Вызов на исполнение производится методом call процедурного объекта. Смотрите ниже: obj = proc{print "Hello world\n"}
obj.call ^D Hello world C-программисты обнаружат сходство между процедурными объектами и указателями на функции. ЗаключениеЭта часть является заключительной в серии. Цель серии была -- дать начальные сведения о программировании на языке Ruby. Я сейчас слишком занят своим дипломным проектом, чтобы выделить время на более глубокое изучение Ruby. Но в будущем, как только позволит время, я это продолжу. Успехов в труде...
Понравилось: 1 пользователю
О проекте
| ||||||||||||||||||