oc语法学习(二)(java对比)

OC NSString/字符串

1.创建NSString对象

1
2
3
4
//最简单的创建字符串对象的方法,使用@
NSString *greeting = @"Hello";
//在java中更简单
String greeting = "hello";

2.调用字符串的方法
(NSString )capitalizedString;
(unichar)characterAtIndex:(NSUInteger)index;
(double)doubleValue;
(float)floatValue;
(BOOL)hasPrefix:(NSString
)aString;
(BOOL)hasSuffix:(NSString )aString;
(id)initWithFormat:(NSString
)format …;
(NSInteger)integerValue;
(BOOL)isEqualToString:(NSString )aString;
(NSUInteger)length;
(NSString
)lowercaseString;
(NSRange)rangeOfString:(NSString )aString;
(NSString
)stringByAppendingFormat:(NSString )format …;
(NSString
)stringByTrimmingCharactersInSet:(NSCharacterSet )set;
(NSString
)substringFromIndex:(NSUInteger)anIndex ;
差异:java中对象调方法,一般是

1
str.method()

而在oc中对象调方法,一般是

1
[str method]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#import <Foundation/Foundation.h>
int main ()
{
//定义两个字符串对象
NSString *str1 = @"Hello";
NSString *str2 = @"World";
//申明一个字符串对象
NSString *str3;
int len ;
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
//将str3的值转成大写
/* uppercase string */
str3 = [str2 uppercaseString];
NSLog(@"Uppercase String : %@
", str3 );
/* concatenates str1 and str2 */
//将str1的值拼接上"world",并赋值给str3
str3 = [str1 stringByAppendingFormat:@"World"];
NSLog(@"Concatenated string: %@
", str3 );
/* total length of str3 after concatenation */
//打印出str3的长度
len = [str3 length];
NSLog(@"Length of Str3 : %d
", len );
/* InitWithFormat */
//将str3通过%@ %@ 格式输出,并将str1和str2替换%@
str3 = [[NSString alloc] initWithFormat:@"%@ %@",str1,str2];
NSLog(@"Using initWithFormat: %@
", str3 );
[pool drain];
return 0;
}

OC struct/结构

1.定义一个结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct [structure tag]
{
member definition;
member definition;
...
member definition;
} [one or more structure variables];
struct Books
{
NSString *title;
NSString *author;
NSString *subject;
int book_id;
} book;

差异:oc的结果很像java中的bean类,通常会这样写

1
2
3
4
5
6
7
类中添加很多字段,然后可以通过book.title调用其属性(事先该属性为public)
class book {
public String title;
public String author;
public String subject;
public int book_id;
}
2.作为函数参数的结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#import <Foundation/Foundation.h>
//定义一个结构
struct Books
{
NSString *title;
NSString *author;
NSString *subject;
int book_id;
};
//定义一个接口
@interface SampleClass:NSObject
/* function declaration */
- (void) printBook:( struct Books) book ;
@end
//接口的实现类
@implementation SampleClass
//实现的方法,形参为Book结构的对象
- (void) printBook:( struct Books) book
{
NSLog(@"Book title : %@
", book.title);
NSLog(@"Book author : %@
", book.author);
NSLog(@"Book subject : %@
", book.subject);
NSLog(@"Book book_id : %d
", book.book_id);
}
@end
int main( )
{
struct Books Book1; /* Declare Book1 of type Book */
struct Books Book2; /* Declare Book2 of type Book */
//给结构里的字段赋值
/* book 1 specification */
Book1.title = @"Objective-C Programming";
Book1.author = @"Nuha Ali";
Book1.subject = @"Objective-C Programming Tutorial";
Book1.book_id = 6495407;
/* book 2 specification */
Book2.title = @"Telecom Billing";
Book2.author = @"Zara Ali";
Book2.subject = @"Telecom Billing Tutorial";
Book2.book_id = 6495700;
SampleClass *sampleClass = [[SampleClass alloc]init];
/* print Book1 info */
[sampleClass printBook: Book1];
//调用printBook方法打印结构中的值
/* Print Book2 info */
[sampleClass printBook: Book2];
return 0;
}
3.指向结构的指针

·定义结构体指针

1
struct Books *struct_yiibaier;
1
2
//存储结构体变量的地址
struct_yiibaier = &Book1;
1
2
//访问成员的结构,使用该结构的一个指针,必须使用->运算符
struct_yiibaier->title;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#import <Foundation/Foundation.h>
//定义一个结构
struct Books
{
NSString *title;
NSString *author;
NSString *subject;
int book_id;
};
//定义一个接口,
@interface SampleClass:NSObject
/* function declaration */
- (void) printBook:( struct Books *) book ;
@end
//接口的实现类
@implementation SampleClass
//方法打印出结构的字段
- (void) printBook:( struct Books *) book
{
//参数为指向结构的指针,所以要使用->获取变量
NSLog(@"Book title : %@
", book->title);
NSLog(@"Book author : %@
", book->author);
NSLog(@"Book subject : %@
", book->subject);
NSLog(@"Book book_id : %d
", book->book_id);
}
@end
int main( )
{
struct Books Book1; /* Declare Book1 of type Book */
struct Books Book2; /* Declare Book2 of type Book */
/* book 1 specification */
Book1.title = @"Objective-C Programming";
Book1.author = @"Nuha Ali";
Book1.subject = @"Objective-C Programming Tutorial";
Book1.book_id = 6495407;
/* book 2 specification */
Book2.title = @"Telecom Billing";
Book2.author = @"Zara Ali";
Book2.subject = @"Telecom Billing Tutorial";
Book2.book_id = 6495700;
SampleClass *sampleClass = [[SampleClass alloc]init];
/* print Book1 info by passing address of Book1 */
[sampleClass printBook:&Book1];
/* print Book2 info by passing address of Book2 */
[sampleClass printBook:&Book2];
return 0;
}

位域

位域允许在一个结构中的数据的包装。
也就是添加该字段所占的长度

1
2
3
4
5
6
7
8
struct packed_struct {
unsigned int f1:1;
unsigned int f2:1;
unsigned int f3:1;
unsigned int f4:1;
unsigned int type:4;
unsigned int my_int:9;
} pack;

预处理器

oc的井号(#)开头的所有预处理命令,和java的其实很像,如#import就类似于java的import类库,还有#if,#else,等等,

预定义宏

预定义宏不应该直接被修改,就是系统提供的特定方法,或者说是特定变量,如DATE, TIME等,这些方法就像java的getDate(),System.currentTimeMillis()等,都是系统提供的方法。

预处理运算符

1.宏延续()
宏通常必须在一个单一的行,宏延续运算符用于继续宏的一行
2.Stringize(#)
在宏定义内使用时,一个宏参数转换成一个字符串常量
3.标记粘贴(##)
标记粘贴运算符在宏定义内结合两个参数,
4.defined()运算符

#defined定义一个标识符,如果指定的标识符被定义,该值是真,如果符号没有定义,这个值是false

5.参数化宏

1
2
3
4
5
int square(int x) {
return x * x;
}
//重写
#define square(x) ((x) * (x))

带参数的宏,必须使用才可以使用#define指令定义。

typedef

type关键字,可以用一个新的名字给一个类型,如

1
2
3
4
//unsigned char类型,使用BYTE给该类型取一个新的名字
typedef unsigned char BYTE;
//使用标识符BYTE的作为unsinged char类型的缩写来定义这连个变量
BYTE b1, b2;

类型转换

将值从一个类型到另一个显式地使用转换运算符如下:

1
(type_name)expression

并且在OC中,一般使用CGFloat做浮点运算。

1
mean = (CGFloat)sum/count;

该方法非常类似于java的强转

1
2
int a = (int)b;
oc与java的类型转换很类似呀。

正常的算术转换

1
int -> unsigned int -> long -> unsigned long -> long long -> unsigned long long -> float -> double -> long double

类似于java的向上转型和向下转型(强转)的概念。

日志处理

使用NSLog方法

####错误处理
在OC中错误处理由Foundation框架的NSError类提供。
NSError对象包括
1.域名:错误于可以是一个预定义的NSError域或任意字符串描述一个自定义域和域必须为nil。
2.代码:错误的错误代码。
3.用户信息:用户信息字典错误和userInfo可能为nil。

1
2
3
4
NSString *domain = @"com.MyCompany.MyApplication.ErrorDomain";
NSString *desc = NSLocalizedString(@"Unable to complete the process", @"");
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : desc };
NSError *error = [NSError errorWithDomain:domain code:-101 userInfo:userInfo];

####OC 类 & 对象

#####特点
1.类定义在两个不同的部分,即@interface和@implementation。
2.几乎所有东西都以对象的形式。
3.对象接收消息和对象通常被称为接收器。
4.对象包含实例变量。
5.对象和实例变量的范围。
6.类隐藏对象的实现。
7.属性是用来提供访问其他类的类的实例变量。
java的Object类是所有类的超类,而oc中NSObject是所有类的超类,

#####对象分配和初始化
类对象的创建声明

1
2
3
Box box1 = [[Box alloc]init];
在java中
Box box1 = new Box();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#import <Foundation/Foundation.h>
//创建一个继承NSObject类的接口类
@interface Box:NSObject
{
//定义三个属性
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
}
1. 由于实例变量是私有的,只能访问内部类实现,所以要使用该关键字来确保类的实例变量可以在类的外部访问。
@property(nonatomic, readwrite) double height; // Property
//定义一个方法,算体积
-(double) volume;
@end
@implementation Box
@synthesize height;
// 初始化方法
-(id)init
{
self = [super init];
length = 1.0;
breadth = 1.0;
return self;
}
-(double) volume
{
return length*breadth*height;
}
@end
int main( )
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
//创建Box对象
Box *box1 = [[Box alloc]init]; // Create box1 object of type Box
Box *box2 = [[Box alloc]init]; // Create box2 object of type Box
double volume = 0.0; // Store the volume of a box here
//设置对象属性的值
// box 1 specification
box1.height = 5.0;
// box 2 specification
box2.height = 10.0;
//调用对象的方法,计算出体积
// volume of box 1
volume = [box1 volume];
NSLog(@"Volume of Box1 : %f", volume);
// volume of box 2
volume = [box2 volume];
NSLog(@"Volume of Box2 : %f", volume);
[pool drain];
return 0;
}

#####属性
属性,确保类的实例变量可以在类的外部访问。
1.属性由@property开始,说着说着一个关键字
2.在内部创建getter,setter方法

1
2
-(void)setIsDone(BOOL)isDone;
-(BOOL)isDone;

同样的,在java中,我们会将对象的属性写成私有的,然后通过getter和setter方法来获取所需的属性。

1
2
3
4
5
6
7
8
9
10
11
12
public class Box {
private int length;
private int count;
public void setLength(int length) {
this.length = length;
}
public int getLength() {
return length;
}
}

####继承
在java中类与类只允许单继承,接口与接口允许多继承,但是在oc中,是允许多重继承,也就是说,它只能由一个基类,但允许多层次的继承。

1
@interface derived-class: base-class

通过:表示继承,也是同样的子类可以继承父类的方法和属性,并且能新增自己特有的属性,及方法。

####多态性
java的三大特性:封装,继承,多态,很类似的oc也有这几大特性,只是稍微有点不同罢了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#import <Foundation/Foundation.h>
@interface Shape : NSObject
{
CGFloat area;
}
- (void)printArea;
@end
@implementation Shape
- (void)printArea{
NSLog(@"The area is %f", area);
}
@end
@interface Square : Shape
{
CGFloat length;
}
- (id)initWithSide:(CGFloat)side;
- (void)calculateArea;
@end
@implementation Square
- (id)initWithSide:(CGFloat)side{
length = side;
return self;
}
- (void)calculateArea{
area = length * length;
}
- (void)printArea{
NSLog(@"The area of square is %f", area);
}
@end
@interface Rectangle : Shape
{
CGFloat length;
CGFloat breadth;
}
- (id)initWithLength:(CGFloat)rLength andBreadth:(CGFloat)rBreadth;
@end
@implementation Rectangle
- (id)initWithLength:(CGFloat)rLength andBreadth:(CGFloat)rBreadth{
length = rLength;
breadth = rBreadth;
return self;
}
- (void)calculateArea{
area = length * breadth;
}
@end
int main(int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Square *square = [[Square alloc]initWithSide:10.0];
[square calculateArea];
[square printArea];
Rectangle *rect = [[Rectangle alloc]
initWithLength:10.0 andBreadth:5.0];
[rect calculateArea];
[rect printArea];
[pool drain];
return 0;
}

java和oc都符合oop的多态思想,即他们可以有共同的父类,并且都具备父类的属性和方法,但是他们也有各自特有的属性及方法,如猫,狗,都是动物,但是猫会抓老鼠,狗会看家,这就是多态的思想。

数据封装

数据封装,很熟悉,基本上为了代码的复用性,我们都会选择将数据进行封装。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//创建一个接口类
@interface Adder : NSObject
{
NSInteger total;
}
- (id)initWithInitialNumber:(NSInteger)initialNumber;
- (void)addNumber:(NSInteger)newNumber;
- (NSInteger)getTotal;
@end
@implementation Adder
-(id)initWithInitialNumber:(NSInteger)initialNumber{
total = initialNumber;
return self;
}
- (void)addNumber:(NSInteger)newNumber{
total = total + newNumber;
}
- (NSInteger)getTotal{
return total;
}
@end
int main(int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Adder *adder = [[Adder alloc]initWithInitialNumber:10];
[adder addNumber:5];
[adder addNumber:4];
NSLog(@"The total is %ld",[adder getTotal]);
[pool drain];
return 0;
}

就如上栗子所示,当我们要多次调用同一个方法时,那就将该功能封装起来,方便复用,以及美观。