diff options
Diffstat (limited to 'ru-ru')
-rw-r--r-- | ru-ru/binary-search-ru.html.markdown | 64 | ||||
-rw-r--r-- | ru-ru/c-ru.html.markdown | 9 | ||||
-rw-r--r-- | ru-ru/javascript-ru.html.markdown | 1 | ||||
-rw-r--r-- | ru-ru/php-ru.html.markdown | 35 | ||||
-rw-r--r-- | ru-ru/qt-ru.html.markdown | 158 | ||||
-rw-r--r-- | ru-ru/swift-ru.html.markdown | 264 |
6 files changed, 447 insertions, 84 deletions
diff --git a/ru-ru/binary-search-ru.html.markdown b/ru-ru/binary-search-ru.html.markdown new file mode 100644 index 00000000..9ed62cb8 --- /dev/null +++ b/ru-ru/binary-search-ru.html.markdown @@ -0,0 +1,64 @@ +--- +category: Algorithms & Data Structures +name: Binary Search +contributors: + - ["Abhishek Jaisingh", "http://github.com/abhishekjiitr"] +translators: + - ["Evan K.", "https://github.com/justblah"] +lang: ru-ru +--- + +# Двоичный (бинарный) поиск + +## Зачем использовать двоичный поиск? + +Поиск является одной из главных проблем в области вычислительной техники. На сегодняшний день осуществляется более одного триллиона поисковых запросов в год, поэтому нам нужны алгоритмы, которые могут делать это очень быстро. Двоичный поиск является одним из фундаментальных алгоритмов в информатике. Для его изучения мы освоим теорию, а затем используем её для реализации алгоритма. + +## Вступление + +Самый простой вариант поиска – линейный поиск, но этот подход занимает много времени, и растет линейно, пропорционально набору данных. Пример реализации – начинаем с крайнего левого элемента массива S, один за другим сравниваем искомое значение X с каждым элементом массива S, если X совпадает с элементом S, возвращаем индекс. Если X не совпадает ни с одним из элементов массива S, возвращаем -1. + +``` +Линейный поиск: O (n) Линейная сложность + +Двоичный поиск: O ( log(n) ) Логарифмическая сложность + +``` +``` +def search(arr, x): + + for i in range(len(arr)): + + if arr[i] == x: + return i + + return -1 + +``` + +## Алгоритм двоичного поиска + +Для корректной работы двоичного поиска набор данных для поиска должен быть отсортирован (в любом порядке). + +### Алгоритм + +``` +Главная идея двоичного поиска заключается в использовании информации о том, что массив уже отсортирован, +что и позволяет упростить сложность алгоритма до O(Logn). Мы попросту отбрасываем половину элементов набора сразу после одного сравнения. +1) Сравнить X с элементом в середине набора S. +2) Если X равен элементу в середине - возвращаем индекс среднего элемента. +3) Если значение X больше, чем средний элемент набора, значит X находится в правой части набора. Повторяем алгоритм для правой половины набора. +4) В противном случае (X меньше) повторяем алгоритм для левой половины набора. +Это и есть рекурсивная реализация двоичного поиска. + +``` + +### На заметку + +Существует и другая форма двоичного поиска, которая можеть быть полезна. + +## На почитать + +* [Проектирование, реализация и примеры](https://ru.wikipedia.org/wiki/%D0%94%D0%B2%D0%BE%D0%B8%D1%87%D0%BD%D1%8B%D0%B9_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA) +* [Описание алгоритма ИТМО](http://neerc.ifmo.ru/wiki/index.php?title=%D0%A6%D0%B5%D0%BB%D0%BE%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B4%D0%B2%D0%BE%D0%B8%D1%87%D0%BD%D1%8B%D0%B9_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA) +* [Ошибки при реализации бинарного поиска](https://habrahabr.ru/post/146228/) diff --git a/ru-ru/c-ru.html.markdown b/ru-ru/c-ru.html.markdown index 5e967181..ab4be57e 100644 --- a/ru-ru/c-ru.html.markdown +++ b/ru-ru/c-ru.html.markdown @@ -145,7 +145,7 @@ int main() { f1 / f2; // => 0.5, плюс-минус погрешность потому что, // цифры с плавающей точкой вычисляются неточно! - // Модуль + // Остаток от деления 11 % 3; // => 2 // Операции сравнения вам уже знакомы, но в Си нет булевого типа. @@ -286,7 +286,7 @@ int main() { // => Напечатает "8, 4" в 64 битной системе // Для того, чтобы получить значение по адресу, напечатайте * перед именем. - // Да, использование * при объявлении указателя и получении значения по адресу + // Да, * используется при объявлении указателя и для получении значения по адресу // немного запутано, но вы привыкнете. printf("%d\n", *px); // => Напечаатет 0, значение перемененной x @@ -305,8 +305,9 @@ int main() { // Объявление указателя на int с адресом массива. int* x_ptr = x_array; // x_ptr сейчас указывает на первый элемент массива (со значением 20). - // Это рабоатет, потому что имя массива возвращает указатель на первый элемент. - // Например, когда массив передаётся в функцию или назначается указателю, он + // Это работает, потому что при обращении к имени массива возвращается + // указатель на первый элемент. + // Например, когда массив передаётся в функцию или присваивается указателю, он // невявно преобразуется в указатель. // Исключения: когда массив является аргументом для оператор '&': int arr[10]; diff --git a/ru-ru/javascript-ru.html.markdown b/ru-ru/javascript-ru.html.markdown index 54499f46..1f1ffce6 100644 --- a/ru-ru/javascript-ru.html.markdown +++ b/ru-ru/javascript-ru.html.markdown @@ -359,6 +359,7 @@ myFunc(); // = undefined // И наоборот, функция может быть присвоена объекту и получать доступ к нему // через this, даже если она не была прикреплена к нему при объявлении. var myOtherFunc = function() { + return this.myString.toUpperCase(); } myObj.myOtherFunc = myOtherFunc; myObj.myOtherFunc(); // = "ПРИВЕТ, МИР!" diff --git a/ru-ru/php-ru.html.markdown b/ru-ru/php-ru.html.markdown index 42c4d360..b5feb105 100644 --- a/ru-ru/php-ru.html.markdown +++ b/ru-ru/php-ru.html.markdown @@ -58,7 +58,8 @@ $int1 = 12; // => 12 $int2 = -12; // => -12 $int3 = 012; // => 10 (ведущий 0 обозначает восьмеричное число) $int4 = 0x0F; // => 15 (ведущие символы 0x означают шестнадцатеричное число) - +// Двоичная запись integer доступна начиная с PHP 5.4.0. +$int5 = 0b11111111; // 255 (0b в начале означает двоичное число) // Дробные числа $float = 1.234; $float = 1.2e3; @@ -86,8 +87,9 @@ $dbl_quotes = "This is a $sgl_quotes."; // => 'This is a $String.' // Специальные (escape) символы работают только в двойных кавычках $escaped = "This contains a \t tab character."; $unescaped = 'This just contains a slash and a t: \t'; - // Заключайте переменные в фигурные скобки, если это необходимо +$apples = "I have {$number} apples to eat."; +$oranges = "I have ${number} oranges to eat."; $money = "I have $${number} in the bank."; // Начиная с PHP 5.3, синтаксис nowdocs может использоваться для @@ -140,11 +142,20 @@ $associative = array('One' => 1, 'Two' => 2, 'Three' => 3); $associative = ['One' => 1, 'Two' => 2, 'Three' => 3]; echo $associative['One']; // печатает 1 +// Добавить элемент в ассоциативный массив +$associative['Four'] = 4; + // Список тоже содержит целочисленные ключи $array = ['One', 'Two', 'Three']; echo $array[0]; // => "One" +// Добавить элемент в конец массива +$array[] = 'Four'; +// или +array_push($array, 'Five'); +// удалить элемент из массива +unset($array[3]); /******************************** * Вывод @@ -184,6 +195,10 @@ $y = 0; echo $x; // => 2 echo $z; // => 0 +// Вывести тип и значение переменной в stdout +var_dump($z); // печатает int(0) +// Напечатать переменную в stdout в удобочитаемом виде +print_r($array); // печатает: Array ( [0] => One [1] => Two [2] => Three ) /******************************** * Логические выражения @@ -204,12 +219,21 @@ assert($c > $b); // больше assert($a <= $b); // меньше или равно assert($c >= $d); // больше или равно -// Следующие утверждения истинны, если переменные имеют одинаковый тип. +// Следующие утверждения истинны, если переменные имеют одинаковые тип. assert($c === $d); assert($a !== $d); assert(1 == '1'); assert(1 !== '1'); +// 'Spaceship' оператор (с PHP 7) используется для сравнения двух выражений. +// Возвращает -1, 0 или 1, когда выражение слева меньше, равно или больше +// выражения справа. +$a = 100; +$b = 1000; + +echo $a <=> $a; // 0, выражения равны +echo $a <=> $b; // -1, $a < $b +echo $b <=> $a; // 1, $b > $a // Переменные могут изменять тип в зависимости от их использования. $integer = 1; echo $integer + $integer; // => 2 @@ -265,6 +289,11 @@ if (false) { // Тернарный оператор print (false ? 'Does not get printed' : 'Does'); +// сокращенная запись тернарного оператора с PHP 5.3 +// эквивалентно "$x ? $x : 'Does'" +$x = false; +print($x ?: 'Does'); + $x = 0; if ($x === '0') { print 'Does not print'; diff --git a/ru-ru/qt-ru.html.markdown b/ru-ru/qt-ru.html.markdown new file mode 100644 index 00000000..d0a70c9d --- /dev/null +++ b/ru-ru/qt-ru.html.markdown @@ -0,0 +1,158 @@ +--- +category: tool +tool: Qt Framework +language: c++ +filename: learnqt-ru.cpp +contributors: + - ["Aleksey Kholovchuk", "https://github.com/vortexxx192"] +translators: + - ["Evan K.", "https://github.com/justblah"] +lang: ru-ru +--- + +**Qt** является широко известным фреймворком для разработки кросс-платформенного программного обеспечения, которое может быть запущено на различных программно-аппаратных платформах практически без изменений в коде, сохраняя при этом мощность и скорость нативных приложений. Хоть **Qt** и был изначально написан на *C++*, у него есть реализации и на других языках: *PyQt*, *QtRuby*, *PHP-Qt* и т.д. + +**Qt** отлично подходит для создания приложений с графическим пользовательским интерфейсом (GUI). Это руководство о том, как сделать это на *C++*. + +```c++ +/* + * Начнём по-старинке + */ + +// все header файлы импортированные из Qt начинаются с заглавной 'Q' +#include <QApplication> +#include <QLineEdit> + +int main(int argc, char *argv[]) { + // создаем объект для управления данными приложения + QApplication app(argc, argv); + + // создаем редактируемую строку и отобразим её на экране + QLineEdit lineEdit("Hello world!"); + lineEdit.show(); + + // запускаем цикл для обработки событий (event loop) + return app.exec(); +} +``` + +GUI часть **Qt** полностью состоит из *виджетов* и *связей* между ними. + +[(EN) ПОДРОБНЕЕ О ВИДЖЕТАХ](http://doc.qt.io/qt-5/qtwidgets-index.html) + +```c++ +/* + * В этом примере мы отобразим надпись с кнопкой. + * Надпись будет появляться после нажатия на кнопку. + * + * Код на Qt говорит сам за себя. + */ + +#include <QApplication> +#include <QDialog> +#include <QVBoxLayout> +#include <QPushButton> +#include <QLabel> + +int main(int argc, char *argv[]) { + QApplication app(argc, argv); + + QDialog dialogWindow; + dialogWindow.show(); + + // добавляем вертикальное расположение + QVBoxLayout layout; + dialogWindow.setLayout(&layout); + + QLabel textLabel("Thanks for pressing that button"); + layout.addWidget(&textLabel); + textLabel.hide(); + + QPushButton button("Press me"); + layout.addWidget(&button); + + // отображаем скрытую надпись после нажатия на кнопку + QObject::connect(&button, &QPushButton::pressed, + &textLabel, &QLabel::show); + + return app.exec(); +} +``` +Обратите внимание на метод *QObject::connect*. Этот метод соединяет *СИГНАЛЫ* одного объекта со *СЛОТАМИ* другого. + +**Сигналы** отправляются когда с объектами происходят отпределённые события, например, сигнал *нажатие* отправляется когда пользователь нажимает на объект типа QPushButton. + +**Слоты** это *действия*, которые могут быть выполнены в ответ на полученные сигналы. + +[(EN) ПОДРОБНЕЕ О СЛОТАХ И СИГНАЛАХ](http://doc.qt.io/qt-4.8/signalsandslots.html) + + +Далее рассмотрим, как можно не только использовать стандартные виджеты, но и расширять их поведение с помощью наследования. Давайте создадим кнопку и посчитаем, сколько раз она была нажата. Для этого мы определяем наш собственный класс *CounterLabel*. Он должен быть объявлен в отдельном файле из-за специфической архитектуры Qt. + +```c++ +// counterlabel.hpp + +#ifndef COUNTERLABEL +#define COUNTERLABEL + +#include <QLabel> + +class CounterLabel : public QLabel { + Q_OBJECT // макрос Qt, обязателен для всех виджетов + +public: + CounterLabel() : counter(0) { + setText("Counter has not been increased yet"); // метод QLabel + } + +public slots: + // действие, которое будет вызвано в ответ на нажатие + void increaseCounter() { + setText(QString("Counter value: %1").arg(QString::number(++counter))); + } + +private: + int counter; +}; + +#endif // COUNTERLABEL +``` + +```c++ +// main.cpp +// Почти тоже самое, что и в предыдущем примере + +#include <QApplication> +#include <QDialog> +#include <QVBoxLayout> +#include <QPushButton> +#include <QString> +#include "counterlabel.hpp" + +int main(int argc, char *argv[]) { + QApplication app(argc, argv); + + QDialog dialogWindow; + dialogWindow.show(); + + QVBoxLayout layout; + dialogWindow.setLayout(&layout); + + CounterLabel counterLabel; + layout.addWidget(&counterLabel); + + QPushButton button("Push me once more"); + layout.addWidget(&button); + QObject::connect(&button, &QPushButton::pressed, + &counterLabel, &CounterLabel::increaseCounter); + + return app.exec(); +} +``` + +## На почитать +Это всё! Конечно, фреймворк Qt намного объемнее, чем часть, которая была рассмотрена в этом руководстве, так что будьте готовы читать и практиковаться. + +[(EN) ДОКУМЕНТАЦИЯ](http://wiki.qt.io/Main/ru) + +Удачи! diff --git a/ru-ru/swift-ru.html.markdown b/ru-ru/swift-ru.html.markdown index 77987bb3..7ff660e1 100644 --- a/ru-ru/swift-ru.html.markdown +++ b/ru-ru/swift-ru.html.markdown @@ -4,9 +4,11 @@ contributors: - ["Grant Timmerman", "http://github.com/grant"] - ["Christopher Bess", "http://github.com/cbess"] - ["Joey Huang", "http://github.com/kamidox"] + - ["Alexey Nazaroff", "http://github.com/rogaven"] filename: learnswift-ru.swift translators: - ["Dmitry Bessonov", "https://github.com/TheDmitry"] + - ["Alexey Nazaroff", "https://github.com/rogaven"] lang: ru-ru --- @@ -21,6 +23,8 @@ Swift - это язык программирования, созданный к Смотрите еще [начальное руководство](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/RoadMapiOS/index.html) Apple, которое содержит полное учебное пособие по Swift. ```swift +// Версия Swift: 3.0 + // импорт модуля import UIKit @@ -31,10 +35,14 @@ import UIKit // Xcode поддерживает маркеры, чтобы давать примечания своему коду // и вносить их в список обозревателя (Jump Bar) // MARK: Метка раздела +// MARK: - Метка с разделителем // TODO: Сделайте что-нибудь вскоре // FIXME: Исправьте этот код -println("Привет, мир") +// Начиная со второй версии Swift, println и print объединены в методе print. +// Перенос строки теперь добавляется в конец автоматически. +print("Привет, мир!") // println – теперь просто print +print("Привет, мир!", terminator: "") // вывод текста без переноса строки // переменные (var), значение которых можно изменить после инициализации // константы (let), значение которых нельзя изменить после инициализации @@ -56,12 +64,12 @@ let piText = "Pi = \(π), Pi 2 = \(π * 2)" // Вставка переменны // Сборка особых значений // используя ключ -D сборки конфигурации #if false - println("Не печатается") + print("Не печатается") let buildValue = 3 #else let buildValue = 7 #endif -println("Значение сборки: \(buildValue)") // Значение сборки: 7 +print("Значение сборки: \(buildValue)") // Значение сборки: 7 /* Опционалы - это особенность языка Swift, которая допускает вам сохранять @@ -79,35 +87,45 @@ var someOptionalString2: Optional<String> = "опционал" if someOptionalString != nil { // я не nil if someOptionalString!.hasPrefix("opt") { - println("содержит префикс") + print("содержит префикс") } - + let empty = someOptionalString?.isEmpty } someOptionalString = nil +/* +Использование ! для доступа к несуществующему опциональному значению генерирует +рантайм ошибку. Всегда проверяйте, что опционал содержит не пустое значение, +перед тем как раскрывать его через !. +*/ + // неявная развертка опциональной переменной var unwrappedString: String! = "Ожидаемое значение." // как и выше, только ! - постфиксный оператор (с еще одним синтаксическим сахаром) var unwrappedString2: ImplicitlyUnwrappedOptional<String> = "Ожидаемое значение." +// If let конструкции - +// If let это специальная конструкция в Swift, которая позволяет проверить Optional +// справа от `=` непустой, и если это так - разворачивает его и присваивает левой части. if let someOptionalStringConstant = someOptionalString { - // имеется некоторое значение, не nil + // имеется некоторое (`Some`) значение, не `nil` if !someOptionalStringConstant.hasPrefix("ok") { // нет такого префикса } } // Swift поддерживает сохранение значения любого типа +// Для этих целей есть два ключевых слова `Any` и `AnyObject` // AnyObject == id -// В отличие от `id` в Objective-C, AnyObject работает с любым значением (Class, -// Int, struct и т.д.) -var anyObjectVar: AnyObject = 7 -anyObjectVar = "Изменять значение на строку не является хорошей практикой, но возможно." +// `Any` же, в отличие от `id` в Objective-C, `Any` работает с любым значением (Class, Int, struct и т.д.) +var anyVar: Any = 7 +anyVar = "Изменять значение на строку не является хорошей практикой, но возможно." +let anyObjectVar: AnyObject = Int(1) as NSNumber /* Комментируйте здесь - + /* Вложенные комментарии тоже поддерживаются */ @@ -129,6 +147,7 @@ shoppingList[1] = "бутылка воды" let emptyArray = [String]() // let == неизменный let emptyArray2 = Array<String>() // как и выше var emptyMutableArray = [String]() // var == изменяемый +var explicitEmptyMutableStringArray: [String] = [] // так же как и выше // Словарь @@ -140,31 +159,39 @@ occupations["Jayne"] = "Связи с общественностью" let emptyDictionary = [String: Float]() // let == неизменный let emptyDictionary2 = Dictionary<String, Float>() // как и выше var emptyMutableDictionary = [String: Float]() // var == изменяемый +var explicitEmptyMutableDictionary: [String: Float] = [:] // то же // // MARK: Поток управления // +// С помощью "," можно указать дополнительные условия для раскрытия +// опциональных значений. +let someNumber = Optional<Int>(7) +if let num = someNumber, num > 3 { + print("Больше 3х") +} + // цикл for для массива let myArray = [1, 1, 2, 3, 5] for value in myArray { if value == 1 { - println("Один!") + print("Один!") } else { - println("Не один!") + print("Не один!") } } // цикл for для словаря var dict = ["один": 1, "два": 2] for (key, value) in dict { - println("\(key): \(value)") + print("\(key): \(value)") } // цикл for для диапазона чисел for i in -1...shoppingList.count { - println(i) + print(i) } shoppingList[1...2] = ["бифштекс", "орехи пекан"] // используйте ..< для исключения последнего числа @@ -176,8 +203,8 @@ while i < 1000 { } // цикл do-while -do { - println("привет") +repeat { + print("привет") } while 1 == 2 // Переключатель @@ -204,7 +231,7 @@ default: // обязательный (чтобы предусмотреть вс // Функции являются типом первого класса, т.е. они могут быть вложены в функциях // и могут передаваться между собой -// Функция с документированным заголовком Swift (формат reStructedText) +// Функция с документированным заголовком Swift (формат Swift-модифицированный Markdown) /** Операция приветствия @@ -212,20 +239,20 @@ default: // обязательный (чтобы предусмотреть вс - Маркер в документировании - Еще один маркер в документации - :param: name - это имя - :param: day - это день - :returns: Строка, содержащая значения name и day. + - Parameter name : Это имя + - Parameter day : Это день + - Returns : Строка, содержащая значения name и day. */ func greet(name: String, day: String) -> String { return "Привет \(name), сегодня \(day)." } -greet("Боб", "вторник") +greet(name: "Боб", day: "вторник") // как и выше, кроме обращения параметров функции -func greet2(#requiredName: String, externalParamName localParamName: String) -> String { - return "Привет \(requiredName), сегодня \(localParamName)" +func greet2(name: String, externalParamName localParamName: String) -> String { + return "Привет \(name), сегодня \(localParamName)" } -greet2(requiredName:"Иван", externalParamName: "воскресенье") +greet2(name: "Иван", externalParamName: "Воскресенье") // Функция, которая возвращает множество элементов в кортеже func getGasPrices() -> (Double, Double, Double) { @@ -235,8 +262,31 @@ let pricesTuple = getGasPrices() let price = pricesTuple.2 // 3.79 // Пропускайте значения кортежей с помощью подчеркивания _ let (_, price1, _) = pricesTuple // price1 == 3.69 -println(price1 == pricesTuple.1) // вывод: true -println("Цена газа: \(price)") +print(price1 == pricesTuple.1) // вывод: true +print("Цена газа: \(price)") + +// Именованные параметры кортежа +func getGasPrices2() -> (lowestPrice: Double, highestPrice: Double, midPrice: Double) { + return (1.77, 37.70, 7.37) +} +let pricesTuple2 = getGasPrices2() +let price2 = pricesTuple2.lowestPrice +let (_, price3, _) = pricesTuple2 +print(pricesTuple2.highestPrice == pricesTuple2.1) // вывод: true +print("Самая высокая цена за газ: \(pricesTuple2.highestPrice)") + +// guard утверждения +func testGuard() { + // guards обеспечивают прерывание дальнейшего выполнения функции, + // позволяя держать обработчики ошибок рядом с проверкой условия + // Объявляемая переменная находится в той же области видимости, что и guard. + guard let aNumber = Optional<Int>(7) else { + return + } + + print("число равно \(aNumber)") +} +testGuard() // Переменное число аргументов func setup(numbers: Int...) { @@ -246,7 +296,7 @@ func setup(numbers: Int...) { } // Передача и возврат функций -func makeIncrementer() -> (Int -> Int) { +func makeIncrementer() -> ((Int) -> Int) { func addOne(number: Int) -> Int { return 1 + number } @@ -256,15 +306,15 @@ var increment = makeIncrementer() increment(7) // передача по ссылке -func swapTwoInts(inout a: Int, inout b: Int) { +func swapTwoInts(a: inout Int, b: inout Int) { let tempA = a a = b b = tempA } var someIntA = 7 var someIntB = 3 -swapTwoInts(&someIntA, &someIntB) -println(someIntB) // 7 +swapTwoInts(a: &someIntA, b: &someIntB) +print(someIntB) // 7 // @@ -291,13 +341,13 @@ numbers = numbers.map({ number in 3 * number }) print(numbers) // [3, 6, 18] // Хвостовое замыкание -numbers = sorted(numbers) { $0 > $1 } +numbers = numbers.sorted { $0 > $1 } print(numbers) // [18, 6, 3] // Суперсокращение, поскольку оператор < выполняет логический вывод типов -numbers = sorted(numbers, < ) +numbers = numbers.sorted(by: <) print(numbers) // [3, 6, 18] @@ -307,8 +357,8 @@ print(numbers) // [3, 6, 18] // Структуры и классы имеют очень похожие характеристики struct NamesTable { - let names = [String]() - + let names: [String] + // Пользовательский индекс subscript(index: Int) -> String { return names[index] @@ -316,9 +366,48 @@ struct NamesTable { } // У структур автогенерируемый (неявно) инициализатор -let namesTable = NamesTable(names: ["Me", "Them"]) +let namesTable = NamesTable(names: ["Иван", "Яков"]) let name = namesTable[1] -println("Name is \(name)") // Name is Them +print("Имя :\(name)") // Имя: Яков + +// +// MARK: Обработка ошибок +// + +// Протокол `Error` используется для перехвата выбрасываемых ошибок +enum MyError: Error { + case BadValue(msg: String) + case ReallyBadValue(msg: String) +} + +// фунции помеченные словом `throws` должны вызываться с помощью `try` +func fakeFetch(value: Int) throws -> String { + guard 7 == value else { + throw MyError.ReallyBadValue(msg: "Действительно плохое значение") + } + + return "тест" +} + +func testTryStuff() { + // предполагается, что не будет выброшено никаких ошибок, + // в противном случае мы получим рантайм исключение + let _ = try! fakeFetch(value: 7) + + // Если возникает ошибка, то выполнение продолжится. Но если значение равно nil, + // то результат будет опционалом + let _ = try? fakeFetch(value: 7) + + do { + // обычно try оператор, позволяющий обработать ошибку в `catch` блоке + try fakeFetch(value: 1) + } catch MyError.BadValue(let msg) { + print("Ошибка: \(msg)") + } catch { + // все остальное + } +} +testTryStuff() // // MARK: Классы @@ -329,7 +418,7 @@ println("Name is \(name)") // Name is Them public class Shape { public func getArea() -> Int { - return 0; + return 0 } } @@ -339,7 +428,7 @@ public class Shape { internal class Rect: Shape { var sideLength: Int = 1 - + // Пользовательский сеттер и геттер private var perimeter: Int { get { @@ -350,12 +439,17 @@ internal class Rect: Shape { sideLength = newValue / 4 } } - + + // Вычисляемые свойства должны быть объявлены с помощью `var`, ведь они могут меняться + var smallestSideLength: Int { + return self.sideLength - 1 + } + // Ленивая загрузка свойства // свойство subShape остается равным nil (неинициализированным), // пока не вызовется геттер lazy var subShape = Rect(sideLength: 4) - + // Если вам не нужны пользовательские геттеры и сеттеры, // но все же хотите запустить код перед и после вызовов геттера или сеттера // свойств, вы можете использовать `willSet` и `didSet` @@ -365,19 +459,19 @@ internal class Rect: Shape { print(someIdentifier) } } - + init(sideLength: Int) { self.sideLength = sideLength // последним всегда вызывается super.init, когда init с параметрами super.init() } - + func shrink() { if sideLength > 0 { - --sideLength + sideLength -= 1 } } - + override func getArea() -> Int { return sideLength * sideLength } @@ -400,7 +494,7 @@ let aShape = mySquare as Shape // сравнение экземпляров, в отличие от ==, которая проверяет эквивалентность if mySquare === mySquare { - println("Ага, это mySquare") + print("Ага, это mySquare") } // Опциональная инициализация (init) @@ -409,13 +503,13 @@ class Circle: Shape { override func getArea() -> Int { return 3 * radius * radius } - + // Поместите постфиксный знак вопроса после `init` - это и будет опциональная инициализация, // которая может вернуть nil init?(radius: Int) { self.radius = radius super.init() - + if radius <= 0 { return nil } @@ -423,13 +517,13 @@ class Circle: Shape { } var myCircle = Circle(radius: 1) -println(myCircle?.getArea()) // Optional(3) -println(myCircle!.getArea()) // 3 +print(myCircle?.getArea()) // Optional(3) +print(myCircle!.getArea()) // 3 var myEmptyCircle = Circle(radius: -1) -println(myEmptyCircle?.getArea()) // "nil" +print(myEmptyCircle?.getArea()) // "nil" if let circle = myEmptyCircle { // не будет выполняться, поскольку myEmptyCircle равен nil - println("circle не nil") + print("circle не nil") } @@ -456,12 +550,13 @@ enum Suit { // указывать тип перечисления, когда переменная объявляется явно var suitValue: Suit = .Hearts -// Нецелочисленные перечисления требуют прямого указания значений +// Значения нецелочисленных перечислений должны быть указаны явно +// или могут выводится с помощью функции `rawValue` из имени enum BookName: String { - case John = "Иоанн" + case John case Luke = "Лука" } -println("Имя: \(BookName.John.rawValue)") +print("Имя: \(BookName.John.rawValue)") // Перечисление (enum) со связанными значениями enum Furniture { @@ -469,7 +564,7 @@ enum Furniture { case Desk(height: Int) // Связать с типами String и Int case Chair(String, Int) - + func description() -> String { switch self { case .Desk(let height): @@ -481,9 +576,9 @@ enum Furniture { } var desk: Furniture = .Desk(height: 80) -println(desk.description()) // "Письменный стол высотой 80 см." +print(desk.description()) // "Письменный стол высотой 80 см." var chair = Furniture.Chair("Foo", 40) -println(chair.description()) // "Стул марки Foo высотой 40 см." +print(chair.description()) // "Стул марки Foo высотой 40 см." // @@ -500,23 +595,24 @@ protocol ShapeGenerator { } // Протоколы, объявленные с @objc, допускают необязательные функции, -// которые позволяют вам проверять на соответствие +// которые позволяют вам проверять на соответствие. Для функций также необходимо указать @objc @objc protocol TransformShape { - optional func reshaped() - optional func canReshape() -> Bool + @objc optional func reshape() + @objc optional func canReshape() -> Bool } class MyShape: Rect { var delegate: TransformShape? - + func grow() { sideLength += 2 + // Размещайте знак вопроса перед опционным свойством, методом // или индексом, чтобы не учитывать nil-значение и возвратить nil // вместо выбрасывания ошибки выполнения (т.н. "опционная цепочка") - if let allow = self.delegate?.canReshape?() { + if let reshape = self.delegate?.canReshape?(), reshape { // проверка делегата на выполнение метода - self.delegate?.reshaped?() + self.delegate?.reshape?() } } } @@ -528,42 +624,42 @@ class MyShape: Rect { // `extension`s: Добавляет расширенный функционал к существующему типу -// Класс Square теперь "соответствует" протоколу `Printable` -extension Square: Printable { +// Класс Square теперь "соответствует" протоколу `CustomStringConvertible` +extension Square: CustomStringConvertible { var description: String { return "Площадь: \(self.getArea()) - ID: \(self.identifier)" } } -println("Объект Square: \(mySquare)") +print("Объект Square: \(mySquare)") // Вы также можете расширить встроенные типы extension Int { var customProperty: String { return "Это \(self)" } - + func multiplyBy(num: Int) -> Int { return num * self } } -println(7.customProperty) // "Это 7" -println(14.multiplyBy(3)) // 42 +print(7.customProperty) // "Это 7" +print(14.multiplyBy(num: 3)) // 42 // Обобщения: Подобно языкам Java и C#. Используйте ключевое слово `where`, // чтобы определить условия обобщений. func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? { - for (index, value) in enumerate(array) { + for (index, value) in array.enumerated() { if value == valueToFind { return index } } return nil } -let foundAtIndex = findIndex([1, 2, 3, 4], 3) -println(foundAtIndex == 2) // вывод: true +let foundAtIndex = findIndex(array: [1, 2, 3, 4], valueToFind: 3) +print(foundAtIndex == 2) // вывод: true // Операторы: // Пользовательские операторы могут начинаться с символов: @@ -571,19 +667,33 @@ println(foundAtIndex == 2) // вывод: true // или // Unicode- знаков математики, символов, стрелок, декорации и линий/кубов, // нарисованных символов. -prefix operator !!! {} +prefix operator !!! // Префиксный оператор, который утраивает длину стороны, когда используется -prefix func !!! (inout shape: Square) -> Square { +prefix func !!! (shape: inout Square) -> Square { shape.sideLength *= 3 return shape } // текущее значение -println(mySquare.sideLength) // 4 +print(mySquare.sideLength) // 4 // Используя пользовательский оператор !!!, изменится длина стороны // путем увеличения размера в 3 раза !!!mySquare -println(mySquare.sideLength) // 12 +print(mySquare.sideLength) // 12 + +// Операторы также могут быть обобщенными +infix operator <-> +func <-><T: Equatable> (a: inout T, b: inout T) { + let c = a + a = b + b = c +} + +var foo: Float = 10 +var bar: Float = 20 + +foo <-> bar +print("foo это \(foo), bar это \(bar)") // "foo = 20.0, bar = 10.0" ``` |