Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Geoff Liu 2015-08-28 11:50:04 -06:00
commit f4ab326784
5 changed files with 589 additions and 79 deletions

View File

@ -213,7 +213,7 @@ say $x; #=> 52
# - `if` # - `if`
# Before talking about `if`, we need to know which values are "Truthy" # Before talking about `if`, we need to know which values are "Truthy"
# (represent True), and which are "Falsey" (or "Falsy") -- represent False. # (represent True), and which are "Falsey" (or "Falsy") -- represent False.
# Only these values are Falsey: (), 0, "", Nil, A type (like `Str` or `Int`), # Only these values are Falsey: (), "", Nil, A type (like `Str` or `Int`),
# and of course False itself. # and of course False itself.
# Every other value is Truthy. # Every other value is Truthy.
if True { if True {

View File

@ -11,6 +11,8 @@ lang: ru-ru
Brainfuck (пишется маленькими буквами, кроме начала предложения) - это очень Brainfuck (пишется маленькими буквами, кроме начала предложения) - это очень
маленький Тьюринг-полный язык программирования лишь с 8 командами. маленький Тьюринг-полный язык программирования лишь с 8 командами.
Вы можете испытать brainfuck в вашем браузере с помощью [brainfuck-визуализатора](http://fatiherikli.github.io/brainfuck-visualizer/).
``` ```
Любой символ, кроме "><+-.,[]", игнорируется, за исключением кавычек. Любой символ, кроме "><+-.,[]", игнорируется, за исключением кавычек.

View File

@ -1,105 +1,170 @@
--- ---
language: Objective-C language: Objective-C
filename: LearnObjectiveC.m filename: LearnObjectiveC-ru.m
contributors: contributors:
- ["Eugene Yagrushkin", "www.about.me/yagrushkin"] - ["Eugene Yagrushkin", "www.about.me/yagrushkin"]
- ["Yannick Loriot", "https://github.com/YannickL"] - ["Yannick Loriot", "https://github.com/YannickL"]
- ["Levi Bostian", "https://github.com/levibostian"]
translators: translators:
- ["Evlogy Sutormin", "http://evlogii.com"] - ["Evlogy Sutormin", "http://evlogii.com"]
- ["Dmitry Bessonov", "https://github.com/TheDmitry"]
lang: ru-ru lang: ru-ru
--- ---
Objective-C — компилируемый объектно-ориентированный язык программирования, используемый корпорацией Apple, Objective-C — основной язык программирования, используемый корпорацией Apple
построенный на основе языка Си и парадигм Smalltalk. для операционных систем OS X и iOS и их соответствующих фреймворках Cocoa и
В частности, объектная модель построена в стиле Smalltalk — то есть объектам посылаются сообщения. Cocoa Touch.
Он является объектно-ориентированным языком программирования общего назначения,
который добавляет обмен сообщениями в Smalltalk-стиле к языку программирования C.
```objective_c ```objective_c
// Однострочный комментарий // Однострочные комментарии начинаются с //
/* /*
Многострочный Так выглядят многострочные комментарии
комментарий
*/ */
// Импорт файлов фреймворка Foundation с помощью #import // Импорт заголовочных файлов фреймворка Foundation с помощью #import
// Используйте <>, чтобы импортировать глобальные файлы (обычно фреймворки)
// Используйте "", чтобы импортировать локальные файлы (из проекта)
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "MyClass.h" #import "MyClass.h"
// Точка входа в программу это функция main, // Если вы включили модули для iOS >= 7.0 или OS X >= 10.9 проектов в
// которая возвращает целый тип integer // Xcode 5, вы можете импортировать фреймворки подобным образом:
@import Foundation;
// Точка входа в программу - это функция main,
// которая возвращает целый тип
int main (int argc, const char * argv[]) int main (int argc, const char * argv[])
{ {
// Создание autorelease pool для управления памятью // Создание autorelease pool для управления памятью в программе
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// В место этого воспользуйтесь @autoreleasepool, если вы используете
// автоматический подсчет ссылок (ARC)
@autoreleasepool {
// Используйте NSLog для печати в консоль // Используйте NSLog для печати в консоль
NSLog(@"Hello World!"); // Напечатает строку "Hello World!" NSLog(@"Привет Мир!"); // Напечатает строку "Привет Мир!"
/////////////////////////////////////// ///////////////////////////////////////
// Типы и переменные // Типы и переменные
/////////////////////////////////////// ///////////////////////////////////////
// Простое объявление // Объявление простых типов
int myPrimitive1 = 1; int myPrimitive1 = 1;
long myPrimitive2 = 234554664565; long myPrimitive2 = 234554664565;
// Объявление объектов
// Помещайте * в начало названия объекта для строго типизированного объявления // Помещайте * в начало названия объекта для строго типизированного объявления
MyClass *myObject1 = nil; // Строгая типизация MyClass *myObject1 = nil; // Строгая типизация
id myObject2 = 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"; NSString *worldString = @"Мир";
NSLog(@"Hello %@!", worldString); // напечатает "Hello World!" NSLog(@"Привет %@!", worldString); // напечатает "Привет Мир!"
// NSMutableString - это изменяемая версия NSString-объекта
NSMutableString *mutableString = [NSMutableString stringWithString:@"Привет"];
[mutableString appendString:@" Мир!"];
NSLog(@"%@", mutableString); // напечатает => "Привет Мир!"
// Символьные литералы // Символьные литералы
NSNumber *theLetterZNumber = @'Z'; NSNumber *theLetterZNumber = @'Z';
char theLetterZ = [theLetterZNumber charValue]; char theLetterZ = [theLetterZNumber charValue]; // или 'Z'
NSLog(@"%c", theLetterZ); NSLog(@"%c", theLetterZ);
// Целочисленный литералы // Целочисленные литералы
NSNumber *fortyTwoNumber = @42; NSNumber *fortyTwoNumber = @42;
int fortyTwo = [fortyTwoNumber intValue]; int fortyTwo = [fortyTwoNumber intValue]; // или '42'
NSLog(@"%i", fortyTwo); NSLog(@"%i", fortyTwo);
// Беззнаковый целочисленный литерал // Беззнаковый целочисленный литерал
NSNumber *fortyTwoUnsignedNumber = @42U; NSNumber *fortyTwoUnsignedNumber = @42U;
unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue]; unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue]; // или 42
NSLog(@"%u", fortyTwoUnsigned); NSLog(@"%u", fortyTwoUnsigned);
NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:42]; NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:42];
short fortyTwoShort = [fortyTwoShortNumber shortValue]; short fortyTwoShort = [fortyTwoShortNumber shortValue]; // или 42
NSLog(@"%hi", fortyTwoShort); NSLog(@"%hi", fortyTwoShort);
NSNumber *fortyOneShortNumber = [NSNumber numberWithShort:41];
unsigned short fortyOneUnsigned = [fortyOneShortNumber unsignedShortValue]; // или 41
NSLog(@"%u", fortyOneUnsigned);
NSNumber *fortyTwoLongNumber = @42L; NSNumber *fortyTwoLongNumber = @42L;
long fortyTwoLong = [fortyTwoLongNumber longValue]; long fortyTwoLong = [fortyTwoLongNumber longValue]; // или 42
NSLog(@"%li", fortyTwoLong); NSLog(@"%li", fortyTwoLong);
NSNumber *fiftyThreeLongNumber = @53L;
unsigned long fiftyThreeUnsigned = [fiftyThreeLongNumber unsignedLongValue]; // или 53
NSLog(@"%lu", fiftyThreeUnsigned);
// Вещественный литерал // Вещественный литерал
NSNumber *piFloatNumber = @3.141592654F; NSNumber *piFloatNumber = @3.141592654F;
float piFloat = [piFloatNumber floatValue]; float piFloat = [piFloatNumber floatValue]; // или 3.141592654f
NSLog(@"%f", piFloat); NSLog(@"%f", piFloat); // напечатает 3.141592654
NSLog(@"%5.2f", piFloat); // напечатает " 3.14"
NSNumber *piDoubleNumber = @3.1415926535; NSNumber *piDoubleNumber = @3.1415926535;
double piDouble = [piDoubleNumber doubleValue]; double piDouble = [piDoubleNumber doubleValue]; // или 3.1415926535
NSLog(@"%f", piDouble); 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 (булевый) литерал // BOOL (булевый) литерал
NSNumber *yesNumber = @YES; NSNumber *yesNumber = @YES;
NSNumber *noNumber = @NO; NSNumber *noNumber = @NO;
// или
BOOL yesBool = YES;
BOOL noBool = NO;
NSLog(@"%i", yesBool); // напечатает 1
// Массив // Массив
// Может содержать различные типы данных, но должен быть объектом Objective-C
NSArray *anArray = @[@1, @2, @3, @4]; NSArray *anArray = @[@1, @2, @3, @4];
NSNumber *thirdNumber = anArray[2]; 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" }; NSDictionary *aDictionary = @{ @"ключ1" : @"значение1", @"ключ2" : @"значение2" };
NSObject *valueObject = aDictionary[@"A Key"]; NSObject *valueObject = aDictionary[@"Ключ"];
NSLog(@"Object = %@", valueObject); // Напечатает "Object = (null)" 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) if (NO)
{ {
NSLog(@"I am never run"); NSLog(@"Я никогда не выполнюсь");
} else if (0) } else if (0)
{ {
NSLog(@"I am also never run"); NSLog(@"Я тоже никогда не выполнюсь");
} else } else
{ {
NSLog(@"I print"); NSLog(@"Я напечатаюсь");
} }
// Ветвление с множественным выбором // Ветвление с множественным выбором
@ -138,15 +203,15 @@ int main (int argc, const char * argv[])
{ {
case 0: case 0:
{ {
NSLog(@"I am never run"); NSLog(@"Я никогда не выполнюсь");
} break; } break;
case 1: case 1:
{ {
NSLog(@"I am also never run"); NSLog(@"Я тоже никогда не выполнюсь");
} break; } break;
default: default:
{ {
NSLog(@"I print"); NSLog(@"Я напечатаюсь");
} break; } break;
} }
@ -170,7 +235,7 @@ int main (int argc, const char * argv[])
// "2," // "2,"
// "3," // "3,"
// // Цикл просмотра // Цикл просмотра
NSArray *values = @[@0, @1, @2, @3]; NSArray *values = @[@0, @1, @2, @3];
for (NSNumber *value in values) for (NSNumber *value in values)
{ {
@ -180,20 +245,32 @@ int main (int argc, const char * argv[])
// "2," // "2,"
// "3," // "3,"
// Цикл for для объектов. Может использоваться с любым объектом Objective-C
for (id item in values) {
NSLog(@"%@,", item);
} // напечатает => "0,"
// "1,"
// "2,"
// "3,"
// Обработка исключений // Обработка исключений
@try @try
{ {
// Ваше исключение здесь // Ваше исключение здесь
@throw [NSException exceptionWithName:@"FileNotFoundException" @throw [NSException exceptionWithName:@"FileNotFoundException"
reason:@"File Not Found on System" userInfo:nil]; reason:@"Файл не найден в системе" userInfo:nil];
} @catch (NSException * e) } @catch (NSException * e)
{ {
NSLog(@"Exception: %@", e); NSLog(@"Исключение: %@", e);
} @finally } @finally
{ {
NSLog(@"Finally"); NSLog(@"В конце отводится время для очистки.");
} // => напечатает "Exception: File Not Found on System" } // => напечатает "Исключение: Файл не найден в системе"
// "Finally" // "В конце отводится время для очистки."
// 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]; MyClass *myObject = [[MyClass alloc] init];
// В Objective-C можель ООП базируется на передаче сообщений. // В Objective-C модель ООП базируется на передаче сообщений.
// В Objective-C Вы не просто вызваете метод; вы посылаете сообщение. // В Objective-C Вы не просто вызваете метод; вы посылаете сообщение.
[myObject instanceMethodWithParameter:@"Steve Jobs"]; [myObject instanceMethodWithParameter:@"Стив Джобс"];
// Очищайте память, перед завершением работы программы. // Очищайте память, перед завершением работы программы.
[pool drain]; [pool drain];
// Конец @autoreleasepool
}
// Конец программы. // Конец программы.
return 0; return 0;
} }
@ -222,63 +302,144 @@ int main (int argc, const char * argv[])
// Синтаксис объявления: // Синтаксис объявления:
// @interface ИмяКласса : ИмяКлассаРодителя <ИмплементируемыеПротоколы> // @interface ИмяКласса : ИмяКлассаРодителя <ИмплементируемыеПротоколы>
// { // {
// Объявление переменных; // тип имя; <= Объявление переменных;
// } // }
// @property тип имя; <= объявление свойств
// -/+ (тип) Объявление метода(ов). // -/+ (тип) Объявление метода(ов).
// @end // @end
@interface MyClass : NSObject <MyProtocol> // NSObject - это базовый класс в Objective-C.
@interface MyClass : NSObject <MyProtocol>
{ {
int count; // Объявления экземпляров переменных (может существовать в файлах интерфейса или реализвации)
id data; int count; // По умолчанию защищенный доступ.
@private id data; // Приватный доступ (Намного удобнее объявлять в файле реализации)
NSString *name; NSString *name;
} }
// При объявлении свойств сразу генерируются геттер и сеттер // Удобное обозначение для переменных с открытым (public) доступом
@property int count; // автоматически генерируется сеттер-метод
@property (copy) NSString *name; // Скопировать объект в ходе присвоения. // По умолчанию название сеттер-метода начинается с 'set' с последующим именем
@property (readonly) id data; // Генерация только геттера // переменной из @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; + (NSString *)classMethod;
+ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight;
// - для метода объекта // - для методов объекта
- (NSString *)instanceMethodWithParameter:(NSString *)string; - (NSString *)instanceMethodWithParameter:(NSString *)string;
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number; - (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: // Имплементируйте методы в файле МойКласс.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 - (void)dealloc
{ {
[height release]; // Если не используется ARC, убедитесь в освобождении переменных объекта класса
[super dealloc]; // and call parent class dealloc
} }
// Конструкторы это способ осздания объектов класса. // Конструкторы это способ создания объектов класса.
// Это обычный конструктор вызываемый при создании объекта клсааа. // Это конструктор по умолчанию, который вызывается, когда объект инициализируется.
- (id)init - (id)init
{ {
if ((self = [super init])) if ((self = [super init])) // 'super' используется для того, чтобы обратиться к методам родительского класса
{ {
self.count = 1; self.count = 1; // 'self' используется для вызова самого себя
} }
return self; return self;
} }
// Можно создать конструкторы, которые содержат аргументы:
- (id)initWithDistance:(int)defaultDistance
{
distance = defaultDistance;
return self;
}
+ (NSString *)classMethod + (NSString *)classMethod
{ {
return [[self alloc] init]; return [[self alloc] init];
} }
+ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight
{
height = defaultHeight;
return [[self alloc] init];
}
- (NSString *)instanceMethodWithParameter:(NSString *)string - (NSString *)instanceMethodWithParameter:(NSString *)string
{ {
return @"New string"; return @"Новая строка";
} }
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number - (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number
@ -286,23 +447,364 @@ int main (int argc, const char * argv[])
return @42; return @42;
} }
// Objective-C не содержит объявление приватных методов, но вы можете имитировать их.
// Чтобы сымитировать приватный метод, создайте метод в @implementation, но не в @interface.
- (NSNumber *)secretPrivateMethod {
return @72;
}
[self secretPrivateMethod]; // Вызывает приватный метод
// Методы объявленные в МyProtocol (см. далее) // Методы объявленные в МyProtocol (см. далее)
- (void)myProtocolMethod - (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(@"Ускорение.");
} }
@end @end
/* // Теперь, если мы хотели создать грузовой объект, мы должны вместо создания подкласса класса Car, как это будет
* Протокол объявляет методы которые должны быть имплементированы // изменять функциональность Car чтобы вести себя подобно грузовику. Но давайте посмотрим, если мы хотим только добавить
* Протокол не является классом. Он просто определяет интерфейс, // функциональность в существующий Car. Хороший пример должен быть чистить автомобиль. Итак мы создадим
* который должен быть имплементирован. // категорию для добавления его очистительных методов:
*/ // @interface ИмяФайла: Car+Clean.h (ИмяБазовогоКласса+ИмяКатегории.h)
#import "Car.h" // Убедитесь в том, что базовый класс импортирован для расширения.
@interface Car (Clean) // Имя категории внутри (), следующие после имени базового класса.
- (void)washWindows; // Названия новых методов, которые мы добавляем в наш объект Car.
- (void)wax;
@protocol MyProtocol
- (void)myProtocolMethod;
@end @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, когда существующий объект освобождается
``` ```
## На почитать ## На почитать

View File

@ -173,6 +173,8 @@ array[1..3] #=> [2, 3, 4]
# Add to an array like this # Add to an array like this
array << 6 #=> [1, 2, 3, 4, 5, 6] array << 6 #=> [1, 2, 3, 4, 5, 6]
# Or like this
array.push(6) #=> [1, 2, 3, 4, 5, 6]
# Check if an item exists in an array # Check if an item exists in an array
array.include?(1) #=> true array.include?(1) #=> true

12
tcl.html.markdown Executable file → Normal file
View File

@ -121,7 +121,8 @@ puts lots\nof\n\n\n\n\n\nnewlines
# A word enclosed in braces is not subject to any special interpretation or # A word enclosed in braces is not subject to any special interpretation or
# substitutions, except that a backslash before a brace is not counted when look#ing for the closing brace # substitutions, except that a backslash before a brace is not counted when
# looking for the closing brace
set somevar { set somevar {
This is a literal $ sign, and this \} escaped This is a literal $ sign, and this \} escaped
brace remains uninterpreted brace remains uninterpreted
@ -163,7 +164,7 @@ set greeting "Hello, $person(name)"
# A namespace holds commands and variables # A namespace holds commands and variables
namespace eval people { namespace eval people {
namespace eval person1 { namespace eval person1 {
set name Neo variable name Neo
} }
} }
@ -189,7 +190,10 @@ set greeting "Hello $people::person1::name"
namespace delete :: namespace delete ::
# Because of name resolution behaviour, it's safer to use the "variable" command to declare or to assign a value to a namespace. # Because of name resolution behaviour, it's safer to use the "variable" command to
# declare or to assign a value to a namespace. If a variable called "name" already
# exists in the global namespace, using "set" here will assign a value to the global variable
# instead of creating a new variable in the local namespace.
namespace eval people { namespace eval people {
namespace eval person1 { namespace eval person1 {
variable name Neo variable name Neo
@ -256,7 +260,7 @@ proc greet greeting\ name return\ \"Hello,\ \$name!
proc fold {cmd args} { proc fold {cmd args} {
set res 0 set res 0
foreach arg $args { foreach arg $args {
set res [cmd $res $arg] set res [$cmd $res $arg]
} }
} }
fold ::tcl::mathop::* 5 3 3 ;# -> 45 fold ::tcl::mathop::* 5 3 3 ;# -> 45