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/objective-c-ru.html.markdown | 654 | 
3 files changed, 864 insertions, 76 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/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, когда существующий объект освобождается +  ```  ## На почитать | 
