diff options
Diffstat (limited to 'ru-ru')
-rw-r--r-- | ru-ru/bash-ru.html.markdown | 284 | ||||
-rw-r--r-- | ru-ru/brainfuck-ru.html.markdown | 2 | ||||
-rw-r--r-- | ru-ru/javascript-ru.html.markdown | 3 | ||||
-rw-r--r-- | ru-ru/objective-c-ru.html.markdown | 654 | ||||
-rw-r--r-- | ru-ru/ruby-ru.html.markdown | 1 |
5 files changed, 865 insertions, 79 deletions
diff --git a/ru-ru/bash-ru.html.markdown b/ru-ru/bash-ru.html.markdown new file mode 100644 index 00000000..21377b6c --- /dev/null +++ b/ru-ru/bash-ru.html.markdown @@ -0,0 +1,284 @@ +--- +category: tool +tool: bash +contributors: + - ["Max Yankov", "https://github.com/golergka"] + - ["Darren Lin", "https://github.com/CogBear"] + - ["Alexandre Medeiros", "http://alemedeiros.sdf.org"] + - ["Denis Arh", "https://github.com/darh"] + - ["akirahirose", "https://twitter.com/akirahirose"] + - ["Anton Strömkvist", "http://lutic.org/"] + - ["Rahil Momin", "https://github.com/iamrahil"] + - ["Gregrory Kielian", "https://github.com/gskielian"] + - ["Etan Reisner", "https://github.com/deryni"] +translators: + - ["Andrey Samsonov", "https://github.com/kryzhovnik"] + - ["Andre Polykanine", "https://github.com/Oire"] +filename: LearnBash-ru.sh +lang: ru-ru +--- + +Bash - это командная оболочка unix (unix shell), которая распространялась как оболочка для операционной системы GNU и используется в качестве оболочки по умолчанию для Linux и Mac OS X. +Почти все нижеприведенные примеры могут быть частью shell-скриптов или исполнены напрямую в shell. + +[Подробнее.](http://www.gnu.org/software/bash/manual/bashref.html) + +```bash +#!/bin/bash +# Первая строка скрипта - это shebang, который сообщает системе, как исполнять +# этот скрипт: http://en.wikipedia.org/wiki/Shebang_(Unix) +# Как вы уже поняли, комментарии начинаются с #. Shebang - тоже комментарий. + +# Простой пример hello world: +echo Hello world! + +# Отдельные команды начинаются с новой строки или разделяются точкой с запятой: +echo 'Это первая строка'; echo 'Это вторая строка' + +# Вот так объявляется переменная: +VARIABLE="Просто строка" + +# но не так: +VARIABLE = "Просто строка" +# Bash решит, что VARIABLE - это команда, которую он должен исполнить, +# и выдаст ошибку, потому что не сможет найти ее. + +# и не так: +VARIABLE= 'Просто строка' +# Тут Bash решит, что 'Просто строка' - это команда, которую он должен исполнить, +# и выдаст ошибку, потому что не сможет найти такой команды +# (здесь 'VARIABLE=' выглядит как присвоение значения переменной, +# но только в контексте исполнения команды 'Просто строка'). + +# Использование переменой: +echo $VARIABLE +echo "$VARIABLE" +echo '$VARIABLE' +# Когда вы используете переменную - присваиваете, экспортируете и т.д. - +# пишите её имя без $. А для получения значения переменной используйте $. +# Заметьте, что ' (одинарные кавычки) не раскрывают переменные в них. + +# Подстановка строк в переменные +echo ${VARIABLE/Просто/A} +# Это выражение заменит первую встреченную подстроку "Просто" на "A" + +# Взять подстроку из переменной +LENGTH=7 +echo ${VARIABLE:0:LENGTH} +# Это выражение вернет только первые 7 символов переменной VARIABLE + +# Значение по умолчанию +echo ${FOO:-"DefaultValueIfFOOIsMissingOrEmpty"} +# Это сработает при отсутствующем значении (FOO=) и пустой строке (FOO=""); +# ноль (FOO=0) вернет 0. +# Заметьте, что в любом случае значение самой переменной FOO не изменится. + +# Встроенные переменные: +# В bash есть полезные встроенные переменные, например +echo "Последнее возвращенное значение: $?" +echo "PID скрипта: $$" +echo "Количество аргументов: $#" +echo "Аргументы скрипта: $@" +echo "Аргументы скрипта, распределённые по отдельным переменным: $1 $2..." + +# Чтение аргументов из устройста ввода: +echo "Как Вас зовут?" +read NAME # Обратите внимание, что нам не нужно определять новую переменную +echo Привет, $NAME! + +# У нас есть обычная структура if: +# наберите 'man test' для получения подробной информации о форматах условия +if [ $NAME -ne $USER ] +then + echo "Имя не совпадает с именем пользователя" +else + echo "Имя совпадает с именем пользователя" +fi + +# Также есть условное исполнение +echo "Исполнится всегда" || echo "Исполнится, если первая команда завершится ошибкой" +echo "Исполнится всегда" && echo "Исполнится, если первая команда выполнится удачно" + +# Можно использовать && и || в выражениях if, когда нужно несколько пар скобок: +if [ $NAME == "Steve" ] && [ $AGE -eq 15 ] +then + echo "Исполнится, если $NAME равно Steve И $AGE равно 15." +fi + +if [ $NAME == "Daniya" ] || [ $NAME == "Zach" ] +then + echo "Исполнится, если $NAME равно Daniya ИЛИ Zach." +fi + +# Выражения обозначаются таким форматом: +echo $(( 10 + 5 )) + +# В отличие от других языков программирования, Bash - это командная оболочка, +# а значит, работает в контексте текущей директории. +# Вы можете просматривать файлы и директории в текущей директории командой ls: +ls + +# У этой команды есть опции: +ls -l # Показать каждый файл и директорию на отдельной строке + +# Результат предыдущей команды может быть направлен на вход следующей. +# Команда grep фильтрует ввод по шаблону. +# Так мы можем просмотреть только *.txt файлы в текущей директории: +ls -l | grep "\.txt" + +# Вы можете перенаправить ввод и вывод команды (stdin, stdout и stderr). +# Следующая команда означает: читать из stdin, пока не встретится ^EOF$, и +# перезаписать hello.py следующим строками (до строки "EOF"): +cat > hello.py << EOF +#!/usr/bin/env python +from __future__ import print_function +import sys +print("#stdout", file=sys.stdout) +print("#stderr", file=sys.stderr) +for line in sys.stdin: + print(line, file=sys.stdout) +EOF + +# Запуск hello.py с разными вариантами перенаправления потоков +# стандартных ввода, вывода и ошибок: +python hello.py < "input.in" +python hello.py > "output.out" +python hello.py 2> "error.err" +python hello.py > "output-and-error.log" 2>&1 +python hello.py > /dev/null 2>&1 +# Поток ошибок перезапишет файл, если этот файл существует, +# поэтому, если вы хотите дописывать файл, используйте ">>": +python hello.py >> "output.out" 2>> "error.err" + +# Переписать output.txt, дописать error.err и сосчитать строки: +info bash 'Basic Shell Features' 'Redirections' > output.out 2>> error.err +wc -l output.out error.err + +# Запустить команду и вывести ее файловый дескриптор (смотрите: man fd) +echo <(echo "#helloworld") + +# Перезаписать output.txt строкой "#helloworld": +cat > output.out <(echo "#helloworld") +echo "#helloworld" > output.out +echo "#helloworld" | cat > output.out +echo "#helloworld" | tee output.out >/dev/null + +# Подчистить временные файлы с подробным выводом ('-i' - интерактивый режим) +rm -v output.out error.err output-and-error.log + +# Команды могут быть подставлены в строку с помощью $( ): +# следующие команды выводят число файлов и директорий в текущей директории. +echo "Здесь $(ls | wc -l) элементов." + +# То же самое можно сделать с использованием обратных кавычек, +# но они не могут быть вложенными, поэтому предпочтительно использовать $( ). +echo "Здесь `ls | wc -l` элементов." + +# В Bash есть структура case, которая похожа на switch в Java и C++: +case "$VARIABLE" in + # Перечислите шаблоны для условий, которые хотите отловить + 0) echo "Тут ноль.";; + 1) echo "Тут один.";; + *) echo "Это не пустое значение.";; +esac + +# Цикл for перебирает элементы переданные в аргументе: +# Содержимое $VARIABLE будет напечатано три раза. +for VARIABLE in {1..3} +do + echo "$VARIABLE" +done + +# Или с использованием "традиционного" синтаксиса цикла for: +for ((a=1; a <= 3; a++)) +do + echo $a +done + +# Цикл for можно использовать для действий с файлами. +# Запустим команду 'cat' для файлов file1 и file2 +for VARIABLE in file1 file2 +do + cat "$VARIABLE" +done + +# ... или выводом из команд +# Запустим cat для вывода из ls. +for OUTPUT in $(ls) +do + cat "$OUTPUT" +done + +# Цикл while: +while [ true ] +do + echo "тело цикла здесь..." + break +done + +# Вы можете определять функции +# Определение: +function foo () +{ + echo "Аргументы работают также, как аргументы скрипта: $@" + echo "и: $1 $2..." + echo "Это функция" + return 0 +} + +# или просто +bar () +{ + echo "Другой способ определить функцию!" + return 0 +} + +# Вызов функции +foo "Мое имя" $NAME + +# Есть много полезных команд, которые нужно знать: +# напечатать последние 10 строк файла file.txt +tail -n 10 file.txt +# напечатать первые 10 строк файла file.txt +head -n 10 file.txt +# отсортировать строки file.txt +sort file.txt +# отобрать или наоборот пропустить повторяющиеся строки (с опцией -d отбирает) +uniq -d file.txt +# напечатать только первую колонку перед символом ',' +cut -d ',' -f 1 file.txt +# заменить каждое 'okay' на 'great' в файле file.txt (regex поддерживается) +sed -i 's/okay/great/g' file.txt +# вывести в stdout все строки из file.txt, совпадающие с шаблоном regex; +# этот пример выводит строки, которые начинаются на "foo" и оканчиваются "bar" +grep "^foo.*bar$" file.txt +# передайте опцию -c чтобы вывести число строк, в которых совпал шаблон +grep -c "^foo.*bar$" file.txt +# чтобы искать по строке, а не шаблону regex, используйте fgrep (или grep -F) +fgrep "^foo.*bar$" file.txt + +# Читайте встроенную документацию оболочки Bash командой 'help': +help +help help +help for +help return +help source +help . + +# Читайте Bash man-документацию +apropos bash +man 1 bash +man bash + +# Читайте документацию info (? для помощи) +apropos info | grep '^info.*(' +man info +info info +info 5 info + +# Читайте bash info документацию: +info bash +info bash 'Bash Features' +info bash 6 +info --apropos bash +``` diff --git a/ru-ru/brainfuck-ru.html.markdown b/ru-ru/brainfuck-ru.html.markdown index 500ac010..fcee185f 100644 --- a/ru-ru/brainfuck-ru.html.markdown +++ b/ru-ru/brainfuck-ru.html.markdown @@ -11,6 +11,8 @@ lang: ru-ru Brainfuck (пишется маленькими буквами, кроме начала предложения) - это очень маленький Тьюринг-полный язык программирования лишь с 8 командами. +Вы можете испытать brainfuck в вашем браузере с помощью [brainfuck-визуализатора](http://fatiherikli.github.io/brainfuck-visualizer/). + ``` Любой символ, кроме "><+-.,[]", игнорируется, за исключением кавычек. diff --git a/ru-ru/javascript-ru.html.markdown b/ru-ru/javascript-ru.html.markdown index 79844565..8655ae4a 100644 --- a/ru-ru/javascript-ru.html.markdown +++ b/ru-ru/javascript-ru.html.markdown @@ -470,9 +470,6 @@ myNumber === myNumberObj; // = false if (0) { // Этот код не выполнится, потому что 0 - это ложь. } -if (Number(0)) { - // Этот код *выполнится*, потому что Number(0) истинно. -} // Впрочем, объекты-обёртки и встроенные типы имеют общие прототипы, // поэтому вы можете расширить функционал строк, например: diff --git a/ru-ru/objective-c-ru.html.markdown b/ru-ru/objective-c-ru.html.markdown index 3246de82..ddff2e5c 100644 --- a/ru-ru/objective-c-ru.html.markdown +++ b/ru-ru/objective-c-ru.html.markdown @@ -1,106 +1,171 @@ --- language: Objective-C -filename: LearnObjectiveC.m +filename: LearnObjectiveC-ru.m contributors: - ["Eugene Yagrushkin", "www.about.me/yagrushkin"] - ["Yannick Loriot", "https://github.com/YannickL"] + - ["Levi Bostian", "https://github.com/levibostian"] translators: - ["Evlogy Sutormin", "http://evlogii.com"] + - ["Dmitry Bessonov", "https://github.com/TheDmitry"] lang: ru-ru --- -Objective-C — компилируемый объектно-ориентированный язык программирования, используемый корпорацией Apple, -построенный на основе языка Си и парадигм Smalltalk. -В частности, объектная модель построена в стиле Smalltalk — то есть объектам посылаются сообщения. +Objective-C — основной язык программирования, используемый корпорацией Apple +для операционных систем OS X и iOS и их соответствующих фреймворках Cocoa и +Cocoa Touch. +Он является объектно-ориентированным языком программирования общего назначения, +который добавляет обмен сообщениями в Smalltalk-стиле к языку программирования C. ```objective_c -// Однострочный комментарий +// Однострочные комментарии начинаются с // /* -Многострочный -комментарий +Так выглядят многострочные комментарии */ -// Импорт файлов фреймворка Foundation с помощью #import +// Импорт заголовочных файлов фреймворка Foundation с помощью #import +// Используйте <>, чтобы импортировать глобальные файлы (обычно фреймворки) +// Используйте "", чтобы импортировать локальные файлы (из проекта) #import <Foundation/Foundation.h> #import "MyClass.h" -// Точка входа в программу это функция main, -// которая возвращает целый тип integer +// Если вы включили модули для iOS >= 7.0 или OS X >= 10.9 проектов в +// Xcode 5, вы можете импортировать фреймворки подобным образом: +@import Foundation; + +// Точка входа в программу - это функция main, +// которая возвращает целый тип int main (int argc, const char * argv[]) { - // Создание autorelease pool для управления памятью + // Создание autorelease pool для управления памятью в программе NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - + // В место этого воспользуйтесь @autoreleasepool, если вы используете + // автоматический подсчет ссылок (ARC) + @autoreleasepool { + // Используйте NSLog для печати в консоль - NSLog(@"Hello World!"); // Напечатает строку "Hello World!" + NSLog(@"Привет Мир!"); // Напечатает строку "Привет Мир!" /////////////////////////////////////// // Типы и переменные /////////////////////////////////////// - // Простое объявление + // Объявление простых типов int myPrimitive1 = 1; long myPrimitive2 = 234554664565; + // Объявление объектов // Помещайте * в начало названия объекта для строго типизированного объявления MyClass *myObject1 = nil; // Строгая типизация id myObject2 = nil; // Слабая типизация - - NSLog(@"%@ and %@", myObject1, [myObject2 description]); // напечатает "(null) and (null)" // %@ – это объект - // 'description' это общий для всех объектов метод вывода данных + // 'description' - это общий для всех объектов метод вывода данных + NSLog(@"%@ and %@", myObject1, [myObject2 description]); // напечатает "(null) and (null)" // Строка - NSString *worldString = @"World"; - NSLog(@"Hello %@!", worldString); // напечатает "Hello World!" + NSString *worldString = @"Мир"; + NSLog(@"Привет %@!", worldString); // напечатает "Привет Мир!" + // NSMutableString - это изменяемая версия NSString-объекта + NSMutableString *mutableString = [NSMutableString stringWithString:@"Привет"]; + [mutableString appendString:@" Мир!"]; + NSLog(@"%@", mutableString); // напечатает => "Привет Мир!" // Символьные литералы NSNumber *theLetterZNumber = @'Z'; - char theLetterZ = [theLetterZNumber charValue]; + char theLetterZ = [theLetterZNumber charValue]; // или 'Z' NSLog(@"%c", theLetterZ); - // Целочисленный литералы + // Целочисленные литералы NSNumber *fortyTwoNumber = @42; - int fortyTwo = [fortyTwoNumber intValue]; + int fortyTwo = [fortyTwoNumber intValue]; // или '42' NSLog(@"%i", fortyTwo); // Беззнаковый целочисленный литерал NSNumber *fortyTwoUnsignedNumber = @42U; - unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue]; + unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue]; // или 42 NSLog(@"%u", fortyTwoUnsigned); NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:42]; - short fortyTwoShort = [fortyTwoShortNumber shortValue]; + short fortyTwoShort = [fortyTwoShortNumber shortValue]; // или 42 NSLog(@"%hi", fortyTwoShort); + NSNumber *fortyOneShortNumber = [NSNumber numberWithShort:41]; + unsigned short fortyOneUnsigned = [fortyOneShortNumber unsignedShortValue]; // или 41 + NSLog(@"%u", fortyOneUnsigned); + NSNumber *fortyTwoLongNumber = @42L; - long fortyTwoLong = [fortyTwoLongNumber longValue]; + long fortyTwoLong = [fortyTwoLongNumber longValue]; // или 42 NSLog(@"%li", fortyTwoLong); + + NSNumber *fiftyThreeLongNumber = @53L; + unsigned long fiftyThreeUnsigned = [fiftyThreeLongNumber unsignedLongValue]; // или 53 + NSLog(@"%lu", fiftyThreeUnsigned); // Вещественный литерал NSNumber *piFloatNumber = @3.141592654F; - float piFloat = [piFloatNumber floatValue]; - NSLog(@"%f", piFloat); + float piFloat = [piFloatNumber floatValue]; // или 3.141592654f + NSLog(@"%f", piFloat); // напечатает 3.141592654 + NSLog(@"%5.2f", piFloat); // напечатает " 3.14" NSNumber *piDoubleNumber = @3.1415926535; - double piDouble = [piDoubleNumber doubleValue]; + double piDouble = [piDoubleNumber doubleValue]; // или 3.1415926535 NSLog(@"%f", piDouble); - + NSLog(@"%4.2f", piDouble); // напечатает "3.14" + + // NSDecimalNumber - это класс с фиксированной точкой, который является + // более точным, чем float или double + NSDecimalNumber *oneDecNum = [NSDecimalNumber decimalNumberWithString:@"10.99"]; + NSDecimalNumber *twoDecNum = [NSDecimalNumber decimalNumberWithString:@"5.002"]; + // NSDecimalNumber не способен использовать стандартные +, -, *, / операторы, + // поэтому он предоставляет свои собственные: + [oneDecNum decimalNumberByAdding:twoDecNum]; + [oneDecNum decimalNumberBySubtracting:twoDecNum]; + [oneDecNum decimalNumberByMultiplyingBy:twoDecNum]; + [oneDecNum decimalNumberByDividingBy:twoDecNum]; + NSLog(@"%@", oneDecNum); // напечатает "10.99", т.к. NSDecimalNumber - изменяемый + // BOOL (булевый) литерал NSNumber *yesNumber = @YES; NSNumber *noNumber = @NO; - + // или + BOOL yesBool = YES; + BOOL noBool = NO; + NSLog(@"%i", yesBool); // напечатает 1 + // Массив + // Может содержать различные типы данных, но должен быть объектом Objective-C NSArray *anArray = @[@1, @2, @3, @4]; NSNumber *thirdNumber = anArray[2]; - NSLog(@"Third number = %@", thirdNumber); // Print "Third number = 3" + NSLog(@"Третье число = %@", thirdNumber); // Напечатает "Третье число = 3" + // NSMutableArray - это изменяемая версия NSArray, допускающая вам изменять + // элементы в массиве и расширять или сокращать массив. + // Удобный, но не эффективный как NSArray. + NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:2]; + [mutableArray addObject:@"Привет"]; + [mutableArray addObject:@"Мир"]; + [mutableArray removeObjectAtIndex:0]; + NSLog(@"%@", [mutableArray objectAtIndex:0]); // напечатает "Мир" // Словарь - NSDictionary *aDictionary = @{ @"key1" : @"value1", @"key2" : @"value2" }; - NSObject *valueObject = aDictionary[@"A Key"]; - NSLog(@"Object = %@", valueObject); // Напечатает "Object = (null)" - + NSDictionary *aDictionary = @{ @"ключ1" : @"значение1", @"ключ2" : @"значение2" }; + NSObject *valueObject = aDictionary[@"Ключ"]; + NSLog(@"Объект = %@", valueObject); // Напечатает "Объект = (null)" + // NSMutableDictionary тоже доступен, как изменяемый словарь + NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithCapacity:2]; + [mutableDictionary setObject:@"значение1" forKey:@"ключ1"]; + [mutableDictionary setObject:@"значение2" forKey:@"ключ2"]; + [mutableDictionary removeObjectForKey:@"ключ1"]; + + // Множество + NSSet *set = [NSSet setWithObjects:@"Привет", @"Привет", @"Мир", nil]; + NSLog(@"%@", set); // напечатает {(Hello, World)} (порядок может отличаться) + // NSMutableSet тоже доступен, как изменяемое множество + NSMutableSet *mutableSet = [NSMutableSet setWithCapacity:2]; + [mutableSet addObject:@"Привет"]; + [mutableSet addObject:@"Привет"]; + NSLog(@"%@", mutableSet); // напечатает => {(Привет)} + /////////////////////////////////////// // Операторы /////////////////////////////////////// @@ -124,13 +189,13 @@ int main (int argc, const char * argv[]) // Условный оператор if (NO) { - NSLog(@"I am never run"); + NSLog(@"Я никогда не выполнюсь"); } else if (0) { - NSLog(@"I am also never run"); + NSLog(@"Я тоже никогда не выполнюсь"); } else { - NSLog(@"I print"); + NSLog(@"Я напечатаюсь"); } // Ветвление с множественным выбором @@ -138,15 +203,15 @@ int main (int argc, const char * argv[]) { case 0: { - NSLog(@"I am never run"); + NSLog(@"Я никогда не выполнюсь"); } break; case 1: { - NSLog(@"I am also never run"); + NSLog(@"Я тоже никогда не выполнюсь"); } break; default: { - NSLog(@"I print"); + NSLog(@"Я напечатаюсь"); } break; } @@ -170,7 +235,7 @@ int main (int argc, const char * argv[]) // "2," // "3," - // // Цикл просмотра + // Цикл просмотра NSArray *values = @[@0, @1, @2, @3]; for (NSNumber *value in values) { @@ -180,20 +245,32 @@ int main (int argc, const char * argv[]) // "2," // "3," + // Цикл for для объектов. Может использоваться с любым объектом Objective-C + for (id item in values) { + NSLog(@"%@,", item); + } // напечатает => "0," + // "1," + // "2," + // "3," + // Обработка исключений @try { // Ваше исключение здесь @throw [NSException exceptionWithName:@"FileNotFoundException" - reason:@"File Not Found on System" userInfo:nil]; + reason:@"Файл не найден в системе" userInfo:nil]; } @catch (NSException * e) { - NSLog(@"Exception: %@", e); + NSLog(@"Исключение: %@", e); } @finally { - NSLog(@"Finally"); - } // => напечатает "Exception: File Not Found on System" - // "Finally" + NSLog(@"В конце отводится время для очистки."); + } // => напечатает "Исключение: Файл не найден в системе" + // "В конце отводится время для очистки." + + // NSError - это полезные объекты для аргументов функции, чтобы заполнить их + // пользовательскими ошибками. + NSError *error = [NSError errorWithDomain:@"Неправильный эл. адрес." code:4 userInfo:nil]; /////////////////////////////////////// // Объекты @@ -203,13 +280,16 @@ int main (int argc, const char * argv[]) // Объект не является полнофункциональным пока обе части не выполнятся. MyClass *myObject = [[MyClass alloc] init]; - // В Objective-C можель ООП базируется на передаче сообщений. + // В Objective-C модель ООП базируется на передаче сообщений. // В Objective-C Вы не просто вызваете метод; вы посылаете сообщение. - [myObject instanceMethodWithParameter:@"Steve Jobs"]; + [myObject instanceMethodWithParameter:@"Стив Джобс"]; // Очищайте память, перед завершением работы программы. [pool drain]; + // Конец @autoreleasepool + } + // Конец программы. return 0; } @@ -222,63 +302,144 @@ int main (int argc, const char * argv[]) // Синтаксис объявления: // @interface ИмяКласса : ИмяКлассаРодителя <ИмплементируемыеПротоколы> // { -// Объявление переменных; +// тип имя; <= Объявление переменных; // } +// @property тип имя; <= объявление свойств // -/+ (тип) Объявление метода(ов). // @end - - -@interface MyClass : NSObject <MyProtocol> +@interface MyClass : NSObject <MyProtocol> // NSObject - это базовый класс в Objective-C. { - int count; - id data; + // Объявления экземпляров переменных (может существовать в файлах интерфейса или реализвации) + int count; // По умолчанию защищенный доступ. + @private id data; // Приватный доступ (Намного удобнее объявлять в файле реализации) NSString *name; } -// При объявлении свойств сразу генерируются геттер и сеттер -@property int count; -@property (copy) NSString *name; // Скопировать объект в ходе присвоения. -@property (readonly) id data; // Генерация только геттера +// Удобное обозначение для переменных с открытым (public) доступом +// автоматически генерируется сеттер-метод +// По умолчанию название сеттер-метода начинается с 'set' с последующим именем +// переменной из @property +@property int propInt; // Имя сеттер-метода = 'setPropInt' +@property (copy) id copyId; // (copy) => Скопировать объект в ходе присвоения. +// (readonly) => Не позволяет установить значение вне @interface +@property (readonly) NSString *roString; // Используйте @synthesize + // в @implementation, чтобы создать аксессор +// Вы можете настроить геттер и сеттер имена вместо используемого 'set'-имени по умолчанию: +@property (getter=lengthGet, setter=lengthSet:) int length; // Методы -+/- (return type)methodSignature:(Parameter Type *)parameterName; ++/- (возвращаемый тип)сигнатураМетода:(Параметр типа *)имяПараметра; // + для методов класса + (NSString *)classMethod; ++ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight; -// - для метода объекта +// - для методов объекта - (NSString *)instanceMethodWithParameter:(NSString *)string; - (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number; -@end +// Методы-конструктор с аргументом: +- (id)initWithDistance:(int)defaultDistance; +// В Objective-C имена методов очень описательные. Всегда имена методов соответствуют своим аргументам + +@end // Устанавливает конец интерфейса (interface) + + +// Чтобы обратиться к открытым (public) переменным из файла реализации, @property генерирует сеттер-метод +// автоматически. Название метода - это 'set' с последующим именем переменной из @property: +MyClass *myClass = [[MyClass alloc] init]; // создает экземпляр объекта класса MyClass +[myClass setCount:10]; +NSLog(@"%d", [myClass count]); // напечатает => 10 +// Или используйте свой геттер и сеттер методы, которые определены в @interface: +[myClass lengthSet:32]; +NSLog(@"%i", [myClass lengthGet]); // напечатает => 32 +// Для удобства вы можете использовать точечную нотацию, +// чтобы установить и получить доступ к переменным объекта: +myClass.count = 45; +NSLog(@"%i", myClass.count); // напечатает => 45 + +// Вызов методов класса: +NSString *classMethodString = [MyClass classMethod]; +MyClass *classFromName = [MyClass myClassFromName:@"Привет"]; + +// Вызов методов экземпляра: +MyClass *myClass = [[MyClass alloc] init]; // Создает экземпляр объекта MyClass +NSString *stringFromInstanceMethod = [myClass instanceMethodWithParameter:@"Привет"]; + +// Селекторы +// Это способ динамически представить методы. Используйте для вызова методов класса, передайте методы +// через функции, чтобы сказать другим классам, что они должны вызвать их и сохранить методы +// как переменные +// SEL - это тип данных. @selector() вернет селектор из предоставленного имени метода +// methodAParameterAsString:andAParameterAsNumber: - это название метода в MyClass +SEL selectorVar = @selector(methodAParameterAsString:andAParameterAsNumber:); +if ([myClass respondsToSelector:selectorVar]) { // Проверяет содержит ли класс метод + // Необходимо установить все аргументы метода в один объект, что отправить его в performSelector-функцию + NSArray *arguments = [NSArray arrayWithObjects:@"Привет", @4, nil]; + [myClass performSelector:selectorVar withObject:arguments]; // Вызывает метод +} else { + // NSStringFromSelector() вернет NSString название метода полученного селектором + NSLog(@"MyClass не содержит метод: %@", NSStringFromSelector(selectedVar)); +} // Имплементируйте методы в файле МойКласс.m: +@implementation MyClass { + long distance; // Переменная экземпляра с закрытым (private) доступом + NSNumber height; +} -@implementation MyClass +// To access a public variable from the interface file, use '_' followed by variable name: +_count = 5; // References "int count" from MyClass interface +// Access variables defined in implementation file: +distance = 18; // References "long distance" from MyClass implementation +// To use @property variable in implementation, use @synthesize to create accessor variable: +@synthesize roString = _roString; // _roString available now in @implementation + +// Called before calling any class methods or instantiating any objects ++ (void)initialize +{ + if (self == [MyClass class]) { + distance = 0; + } +} // Вызывается при высвобождении памяти под объектом - (void)dealloc { + [height release]; // Если не используется ARC, убедитесь в освобождении переменных объекта класса + [super dealloc]; // and call parent class dealloc } -// Конструкторы – это способ осздания объектов класса. -// Это обычный конструктор вызываемый при создании объекта клсааа. +// Конструкторы – это способ создания объектов класса. +// Это конструктор по умолчанию, который вызывается, когда объект инициализируется. - (id)init { - if ((self = [super init])) + if ((self = [super init])) // 'super' используется для того, чтобы обратиться к методам родительского класса { - self.count = 1; + self.count = 1; // 'self' используется для вызова самого себя } return self; } +// Можно создать конструкторы, которые содержат аргументы: +- (id)initWithDistance:(int)defaultDistance +{ + distance = defaultDistance; + return self; +} + (NSString *)classMethod { return [[self alloc] init]; } ++ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight +{ + height = defaultHeight; + return [[self alloc] init]; +} + - (NSString *)instanceMethodWithParameter:(NSString *)string { - return @"New string"; + return @"Новая строка"; } - (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number @@ -286,23 +447,364 @@ int main (int argc, const char * argv[]) return @42; } +// Objective-C не содержит объявление приватных методов, но вы можете имитировать их. +// Чтобы сымитировать приватный метод, создайте метод в @implementation, но не в @interface. +- (NSNumber *)secretPrivateMethod { + return @72; +} +[self secretPrivateMethod]; // Вызывает приватный метод + // Методы объявленные в МyProtocol (см. далее) - (void)myProtocolMethod { - // имплементация + // операторы } +@end // Устанавливает конец реализации (implementation) + +/////////////////////////////////////// +// Категории +/////////////////////////////////////// +// Категория - это группа методов предназначенные для того, чтобы расширить класс. Они позволяют вам добавить новые методы +// к существующему классу для организационных целей. Это не стоит путать с подклассами. +// Подклассы предназначены для ИЗМЕНЕНИЯ функциональности объекта пока как категории ДОБАВЛЯЮТ +// функциональность в объект. +// Категории позволяют вам: +// -- Добавлять методы в существующий класс для организационных целей. +// -- Допускает вам расширять объекты Objective-C классов (напр.: NSString) добавить ваши собственные методы. +// -- Добавляет возможность создать защищенные и закрытые методы классов. +// ПРИМЕЧАНИЕ: Не переопределяйте методы базового класса в категории даже если у вас есть возможность это сделать +// to. Переопределение методов может привести к ошибкам компиляции позднее между различными категориями и это +// нарушает цель категорий, чтобы добавлять только функциональность. Вместо этого подклассы переопределяют методы. + +// Здесь простой базовый класс Car. +@interface Car : NSObject + +@property NSString *make; +@property NSString *color; + +- (void)turnOn; +- (void)accelerate; + @end -/* - * Протокол объявляет методы которые должны быть имплементированы - * Протокол не является классом. Он просто определяет интерфейс, - * который должен быть имплементирован. - */ +// И реализация базового класса Car: +#import "Car.h" + +@implementation Car + +@synthesize make = _make; +@synthesize color = _color; + +- (void)turnOn { + NSLog(@"Машина заведена."); +} +- (void)accelerate { + NSLog(@"Ускорение."); +} -@protocol MyProtocol - - (void)myProtocolMethod; @end + +// Теперь, если мы хотели создать грузовой объект, мы должны вместо создания подкласса класса Car, как это будет +// изменять функциональность Car чтобы вести себя подобно грузовику. Но давайте посмотрим, если мы хотим только добавить +// функциональность в существующий Car. Хороший пример должен быть чистить автомобиль. Итак мы создадим +// категорию для добавления его очистительных методов: +// @interface ИмяФайла: Car+Clean.h (ИмяБазовогоКласса+ИмяКатегории.h) +#import "Car.h" // Убедитесь в том, что базовый класс импортирован для расширения. + +@interface Car (Clean) // Имя категории внутри (), следующие после имени базового класса. + +- (void)washWindows; // Названия новых методов, которые мы добавляем в наш объект Car. +- (void)wax; + +@end + +// @implementation имя файла: Car+Clean.m (ИмяБазовогоКласса+ИмяКатегории.m) +#import "Car+Clean.h" // Импортируйте Очистку файл @interface категории. + +@implementation Car (Clean) + +- (void)washWindows { + NSLog(@"Окна промыли."); +} +- (void)wax { + NSLog(@"Воском натерли."); +} + +@end + +// Любой экземпляр объекта Car имеет возможность воспользоваться категорией. Все, что нужно сделать, это импортировать ее: +#import "Car+Clean.h" // Импортировать как множество различных категорий, как вы хотите использовать. +#import "Car.h" // Кроме того, необходимо импортировать базовый класс для использования его оригинальные функциональные возможности. + +int main (int argc, const char * argv[]) { + @autoreleasepool { + Car *mustang = [[Car alloc] init]; + mustang.color = @"Красный"; + mustang.make = @"Форд"; + + [mustang turnOn]; // Используйте методы из базового класса Car. + [mustang washWindows]; // Используйте методы категории Clean из класса Car. + } + return 0; +} + +// Objective-C не поддерживает объявление защищенных методов, но вы можете имитировать их. +// Создайте категорию, содержащую все защищенные методы, затем импортируйте ее только в +// @implementation-файле класса, относящегося к классу Car: +@interface Car (Protected) // Наименование категории с помощью 'Protected' +// дает знать, что методы защищенные. + +- (void)lockCar; // Здесь перечисляются методы, которые должны быть созданы +// только с помощью объектов класса Car. + +@end +// Чтобы воспользоваться защищенными методами, импортируйте категорию, затем реализуйте методы: +#import "Car+Protected.h" // Запомните, делайте импорт только в файле с @implementation. + +@implementation Car + +- (void)lockCar { + NSLog(@"Машина закрыта."); // Экземпляры класса Car не могут использовать +// метод lockCar, потому что он объявлен не в @interface. +} + +@end + +/////////////////////////////////////// +// Расширения +/////////////////////////////////////// +// Расширения позволяют вам переопределять атрибуты свойств и методов +// с открытым доступом в @interface. +// @interface имя файла: Shape.h +@interface Shape : NSObject // Расширение базового класса Shape переопределяет + // свои поля ниже. + +@property (readonly) NSNumber *numOfSides; + +- (int)getNumOfSides; + +@end +// Вы можете переопределить numOfSides-переменную или getNumOfSides-метод +// Внесение изменений с помощью расширения делается следующим образом: +// @implementation имя файла: Shape.m +#import "Shape.h" +// Расширения "живут" в том же файле, где и @implementation класса. +@interface Shape () // После имени базового класса скобки () объявляют расширение. + +@property (copy) NSNumber *numOfSides; // Делает numOfSides-свойство + // копирующим (copy) вместо свойства только для чтения (readonly). +-(NSNumber)getNumOfSides; // Изменяет метод getNumOfSides так, + // чтобы он возвращал объект NSNumber вместо типа int. +-(void)privateMethod; // Вы также можете создать новый закрытый метод + // внутри расширения. + +@end +// Главный @implementation: +@implementation Shape + +@synthesize numOfSides = _numOfSides; + +-(NSNumber)getNumOfSides { // Все операторы внутри расширения + // должны быть в @implementation. + return _numOfSides; +} +-(void)privateMethod { + NSLog(@"Закрытый метод созданный с помощью расширения."); + NSLog(@"Экземпляр Shape не может вызвать этот метод."); +} + +@end + +/////////////////////////////////////// +// Протоколы +/////////////////////////////////////// +// Протокол объявляет методы, которые могут быть реализованы с помощью +// любого класса. Протоколы сами по себе не являются классами. Они просто +// определяют интерфейс, который должен быть реализован другими объектами. +// @protocol имя файла: "CarUtilities.h" +@protocol CarUtilities <NSObject> // <NSObject> => Имя другого протокола, +// который включен в этот протокол. + @property BOOL engineOn; // Адаптирующий класс должен определить +// все @synthesize для @property и + - (void)turnOnEngine; // определить все методы. +@end +// Ниже пример класса, реализующий протокол. +#import "CarUtilities.h" // Импорт файла с @protocol. + +@interface Car : NSObject <CarUtilities> // Внутри <> имя протокола +// Здесь вам не нужно указывать @property или имена методов для CarUtilities. +// Они нужны только для @implementation. +- (void)turnOnEngineWithUtilities:(id <CarUtilities>)car; // Вы также можете +// указать тип протоколов. +@end +// В @implementation нужно реализовать все @property и методы для протокола. +@implementation Car : NSObject <CarUtilities> + +@synthesize engineOn = _engineOn; // Создайте @synthesize-оператор +// для "@property engineOn". + +- (void)turnOnEngine { // Реализуйте turnOnEngine как вам угодно. Протоколы +// не определят, + _engineOn = YES; // как вам реализовать метод, он только требует, +// чтобы вы реализовали его. +} +// Вы можете использовать протокол как данные, если вы знаете, что он реализует +// методы и переменные. +- (void)turnOnEngineWithCarUtilities:(id <CarUtilities>)objectOfSomeKind { + [objectOfSomeKind engineOn]; // У вас есть доступ к переменным объекта + [objectOfSomeKind turnOnEngine]; // и методам. + [objectOfSomeKind engineOn]; // Может или не может быть значение YES. Класс +// реализует как нужно. +} + +@end +// Экземпляры класса Car сейчас имеют доступ к протоколу. +Car *carInstance = [[Car alloc] init]; +[carInstance setEngineOn:NO]; +[carInstance turnOnEngine]; +if ([carInstance engineOn]) { + NSLog(@"Двигатель запущен."); // напечатает => "Двигатель запущен." +} +// Убедитись в том, что объект типа 'id' реализует протокол перед вызовом методов протокола: +if ([myClass conformsToProtocol:@protocol(CarUtilities)]) { + NSLog(@"Не работает, т.к. класс MyClass не реализует протокол CarUtilities."); +} else if ([carInstance conformsToProtocol:@protocol(CarUtilities)]) { + NSLog(@"Работает как класс Car, который реализует протокол CarUtilities."); +} +// Категории тоже могут реализовать протоколы: +// @interface Car (CarCategory) <CarUtilities> +// Вы можете реализовать много протоколов: +// @interface Car : NSObject <CarUtilities, CarCleaning> +// ЗАМЕЧАНИЕ: Если два или более протоколов полагаются друг на друга, +// убедитесь, что они ранее объявлены: +#import "Brother.h" + +@protocol Brother; // Оператор раннего объявления. Без него компилятор +// выдаст ошибку. + +@protocol Sister <NSObject> + +- (void)beNiceToBrother:(id <Brother>)brother; + +@end + +// Рассмотрите проблему, где протокол Sister полагается на протокол Brother, +// а Brother полагается на Sister. +#import "Sister.h" + +@protocol Sister; // Эти строки предотвращают рекурсию, решая этим проблему. + +@protocol Brother <NSObject> + +- (void)beNiceToSister:(id <Sister>)sister; + +@end + + +/////////////////////////////////////// +// Блоки +/////////////////////////////////////// +// Блоки - это операторы кода, наподобие функции, которую возможно использовать +// как данные. +// Ниже простой блок с целочисленным аргументом, и возвращает аргумент плюс 4. +int (^addUp)(int n); // Объявите переменную, чтобы сохранить блок. +void (^noParameterBlockVar)(void); // Пример объявления блока-переменной +// без аргументов. +// Блоки имею доступ к переменным в той же области видимости. Но переменные +// будут только для чтения, и значения переданных в блок станут значением +// переменной, когда блок создастся. +int outsideVar = 17; // Если мы редактируем outsideVar после объявления addUp, +// outsideVar остается равным 17. +__block long mutableVar = 3; // __block делают переменные перезаписываемыми +// в блоках, в отличие от outsideVar. +addUp = ^(int n) { // Удалите (int n) в блоке, чтобы не принимать +// какие-либо параметры. + NSLog(@"Вы можете иметь столько строк в блоке, сколько вы хотели."); + NSSet *blockSet; // Также вы можете объявить локальные переменные. + mutableVar = 32; // Присвоить новое значение к __block-переменной. + return n + outsideVar; // Необязательный оператор возврата. +} +int addUp = add(10 + 16); // Вызывает блок кода с аргументами. +// Блоки часто используются как аргументы функции, чтобы позже их вызвать, или +// как функции обратного вызова (callbacks). +@implementation BlockExample : NSObject + +- (void)runBlock:(void (^)(NSString))block { + NSLog(@"В аргументе блок ничего не возвращает и принимает NSString-объект."); + block(@"Аргумент передан блоку на исполнение."); // Вызов блока. +} + +@end + + +/////////////////////////////////////// +// Управление памятью +/////////////////////////////////////// +/* +Для каждого объекта, используемого в приложении, должна быть выделена память +для таких объектов. Когда приложение прекращает использование объекта, память +должна быть освобождена, чтобы гарантировать эффективность приложения. +Objective-C не использует сборщик мусора, а вместо этого применяет подсчет ссылок. +Пока существует по крайней мере одна ссылка на объект (также называется +"владение" объектом), то объект будет доступен к использованию (еще известно +как "право владения"). + +Когда экземпляр владеет объектом, его ссылка увеличивается на один. Когда +объекта освобождается, счетчик ссылки уменьшается на один. Когда счетчик ссылки +равен нулю, объект удаляется из памяти. + +Над всеми объектами взаимодействуют, следуя паттерну: +(1) создание объекта, (2) использование объекта, (3) затем освобождение объекта из памяти. +*/ + +MyClass *classVar = [MyClass alloc]; // 'alloc' устанавливает счетчик ссылки +// объекта classVar на 1 и возвращает указатель на объект. +[classVar release]; // Уменьшает счетчик ссылки объекта classVar +// 'retain' заявляет право собственности на существующий экземпляр объекта +// и увеличивает счетчик ссылки. Затем вернет указатель на объект. +MyClass *newVar = [classVar retain]; // Если classVar освободится, объект +// останется в памяти, потому что newVar - владелец +[classVar autorelease]; // Удалит право на владение объектом +// в конце @autoreleasepool блока. Вернет указатель на объект. + +// @property может использовать 'retain' и 'assign' тоже для маленького +// удобного определения +@property (retain) MyClass *instance; // Освободит старое значение и сохранит +// одно новое (строгая ссылка) +@property (assign) NSSet *set; // Укажет на новое значение +// без сохранения/освобождения старого значения (слабая ссылка) + +// Автоматический подсчет ссылок (ARC) +// Управление памятью может быть трудным, поэтому в Xcode 4.2 и iOS 4 введен +// автоматический подсчет ссылок (ARC). +// ARC - это особенность компилятора, который помещает "retain", "release" +// и "autorelease" автоматически за вас тогда, когда используется ARC, +// вам не нужно больше обращаться к "retain", "relase" или "autorelease" +MyClass *arcMyClass = [[MyClass alloc] init]; +// ... код, использующий объект arcMyClass +// Без ARC, вам нужно было бы вызвать: [arcMyClass release] после того, как вы +// завершите работу с объектом arcMyClass. Но с ARC, +// теперь этого не нужно делать. Он будет помещать release-вызов за вас + +// Что касается 'assign' и 'retain' @property атрибутов, в ARC вы должны +// использовать 'weak' и 'strong' +@property (weak) MyClass *weakVar; // 'weak' не принимает право на владение +// объектом. Если исходный счетчик ссылки экземпляра обнуляется, +// weakVar-свойство автоматически примет значение nil, +// во избежание падения приложения +@property (strong) MyClass *strongVar; // 'strong' принимает право на владение +// объектом. Гарантирует, что объект останится в памяти для использования + +// Для обычных переменных (не объявленных с помощью @property), используйте +// следующий способ: +__strong NSString *strongString; // По умолчанию. Переменная сохраняется в памяти, +// пока она не покинет область видимости +__weak NSSet *weakSet; // Слабая ссылка на существующий объект. Когда существующий +// объект освобождается, weakSet принимает nil +__unsafe_unretained NSArray *unsafeArray; // Похож на __weak, но unsafeArray +// не принимает nil, когда существующий объект освобождается + ``` ## На почитать diff --git a/ru-ru/ruby-ru.html.markdown b/ru-ru/ruby-ru.html.markdown index 318e0e09..69b5fb46 100644 --- a/ru-ru/ruby-ru.html.markdown +++ b/ru-ru/ruby-ru.html.markdown @@ -158,6 +158,7 @@ array << 6 #=> [1, 2, 3, 4, 5, 6] hash = {'color' => 'green', 'number' => 5} hash.keys #=> ['color', 'number'] +hash.values #=> ['green', 5] # Значение в хэше легко может быть найдено по ключу: hash['color'] #=> 'green' |