黑马程序员——OC基础—核心语法(上)

本文详细探讨了Objective-C与Swift作为iOS开发语言的优势与区别,介绍了如何在实际项目中灵活运用这两种语言,提升开发效率与代码质量。

---------------------- Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ----------------------

===== 类方法 =====

类方法 : 使用类名来调用的方法以 + 标记.

使用场合使用类方法代替对象方法可以提高性能.

类方法比对象方法优化体现在不用创建对象就能执行行为在内存中, +识别为类方法直接去类的存储空间中调用方法对象方法则需要通过对象指针访问对象通过isa指针访问类空间才能调用到方法.

定义一个类方法 : 声明 + 实现

@interface Person : NSObject
// 声明一个类方法
+ (void) printClassName;
@end
 
@implementation Person
// 类方法的实现
+ (void) printClassName {
        NSLog(@"Class: Person");
}
@end
 
int main() {
        // 使用类名来调用类方法
        [Person printClassName];
        return 0;
}
+开头的方法 和 -开头的方法是不同的类不能调用对象的方法对象不能调用类的方法否则(编译链接可以通过)运行时会报错 -找不到相应的类/对象方法.
 
因为类方法和对象方法不同所以可以有同名的类方法和对象方法.
+ (void) test;
- (void) test;
上面两个方法是可以同时存在的但是不能有两个同名的对象方法.
 
注意成员变量也叫实例变量是只有实例(对象)才有的变量类没有成员变量在内存中对象里有存储空间存放成员变量的值,类的空间里是没有存放成员变量的地方的所以类没有成员变量的值, 类方法不能访问成员变量.
 
所以如果方法中需要访问成员变量就要写成对象方法如果不需要访问成员变量就可以写成类方法.
 
类方法的好处: 不依赖于对象执行效率高能用类方法(不需要成员变量)尽量用类方法.
使用当方法内部不需要访问成员变量时就可以使用类方法.

===== self 关键字的使用 ===== 

self 是个指针指向调用它的变量 (可能是类也可能是对象).谁调用它,它就指向谁。
self关键字不以@开头.
 1>使用self调用成员变量:
 
@interface Person : NSObject
{
        int _age;
}
- (void) setAge:(int)age;
- (int) age;
- (void) printAge;
@end
 
在对象的方法里可以使用self关键字, self就指向调用这个方法的对象.
- (void) setAge:(int)age {
        self->_age = age;//和 _age = age; 等价
}
 
 
2>使用self调用对象方法或者类方法:
 
- (void) bark {
        NSLog(@"Woof!");
}
- (void) barkAndYell {
        [self bark];      // 使用self其它对象方法
        NSLog(@"Wooooooool");
}
 
 
注意:1> 注意如果在方法内部调用这个方法本身会造成递归可能会导致无限循环.
      2> 注意对象方法中的self代表对象如果调用其它方法调用的是对象方法类方法中的self代表调用的类方法中使用self调用的是类方          法. (Java中的this只能代表对象不能代表类). 对象方法中的self不能去调用类方法类方法中的self不能去调用对象方法.
      3> self不能去调用函数函数只能通过函数名(参数)方式调用不可以通过self调用. 

===== 构造方法 ===== 

构造方法就是初始化对象的方法.
 
 
系统默认的方法为 new 方法,+new是一个类方法用来创建一个对象但是new方法把所有属性的值初始化为0, 在开发中不常用.
 
 
new方法包括 +alloc 方法 与 -init方法,其中 +alloc 方法分配空间,-init方法初始化对象(系统默认值为0)。
 
 
 

=== 重写init方法 ===

 
init就是构造方法用来初始化对象构造方法是对象方法因为它需要设置成员变量的值.
默认构造方法中所有的成员变量的值都设为0. 我们想让新建对象时成员变量的默认值不是0, 可以自己重写构造方法.
 
-init 的方法是父类NSObject的方法可以在子类中重写.
 
 
在类的实现中重写 (重写方法可以不用声明直接实现就可以)
 
@implementation Person
- (id) init {
        // 必须要先调用父类的init方法进行初始化因为父类中声明的成员变量子类也有,  需要在init中初始化(比如把isa指针指向类).
        self = [super init];      // 初始化父类的成员变量返回初始化好的对象
        // 判断是否初始化成功
        if (self != nil) {
                // 给当前类的成员变量赋值
                _age = 20;
        }
        // 返回已经初始化完毕的对象
        return self;
}
@end
 

也可以简写成如下形式:

- (id) init {

        if (self = [super init]) {     // 调用父类方法初始化并判断self是否有值

                _age = 20;              // 给成员变量赋值

        }

        return self;                      // 返回初始化完毕的对象

}

这样写后,声明的Person类的年龄都是20。

重写init方法时对象的成员变量初始值只能是固定的值自定义构造方法可以在初始化时给成员变量赋不同的初值.
 
自定义构造方法
自定义的构造方法需要声明和实现 (重写父类的方法不需要声明)
 
自定义构造方法的规范 :
1> 是对象方法
2> 返回值是id类型
3> 方法名以init开头 (方便程序员之间的交流一看就知道是构造方法)
4> 方法内部的格式和重写init的格式相同 : 调用super的方法并判断空值给自己的成员变量赋值返回对象
5> 注意如果有继承通常只给自己的成员变量直接赋值父类的成员变量通过调用父类的初始化方法对其赋值
@interface Person : NSObject
@property NSString *name;
@property int age;
// 添加自定义构造方法
- (id) initWithName:(NSString *)name;
- (id) initWithName:(NSString *)name andAge:(int)age;
@end
 
@implementation Person
// 重写init方法默认名字为John
- (id) init {
        if (self = [super init]) {
                _name = @"John";
        }
        return self;
}
// 实现自定义的构造方法
- (id) initWithName:(NSString *)name {
        if (self = [super init]) {                  // 和重写init方法是同样的步骤
                _name = name;
        }
        return self;
}
- (id) initWithName:(NSString *)name andAge:(int)age {
        if (self = [super init]) {
                _name = name;
                _age = age;
        }
        return self;
}
@end
 
int main() {
        Person *p = [[Person alloc] initWithName:@"Rose" andAge:18];     // 调用自己写的初始化方法新建对象
        return 0;
}  
子类对象的初始化 #
比如, Student类是Person的子类Person类多了一个属性_no, 我们想给Student添加初始化方法
@interface Student : Person
@property int no;
- (id) initWithNo:(int)no;
- (id) initWithName:(NSString *)name andAge:(int)age andNo:(int)no;
@end
 
@implementation Student
- (id) initWithNo:(int)no {
        if (self = [super init]) {
                _no = no;
        }
        return self;
}
- (id) initWithName:(NSString *)name andAge:(int)age andNo:(int)no {
        if (self = [super init]) {
                _no = no;
                // _name = name; 错误因为_name在父类中是@private, 不可以通过_name访问
                // [self setName:name];     可以使用set方法设置但是不建议
                // self.age = age;               也可以使用点语法但是也不建议这样做
                // 如何合理的初始化父类提供的属性最好使用父类的初始化方法见下面
        }
        return self;
}
@end
 
int main() {
        Student *s = [[Student alloc] initWithNo:2];
        return 0;
}

 
新建Student对象并把学号赋值为2, 会发现s_name属性的值为"John", 因为在Personinit方法中将_name默认值赋值为"John".
如果要给Student对象赋父类的成员变量值不能直接使用父类的成员变量名(私有), 要调用父类的set方法给成员变量赋值但是不建议这么做最好使用父类的初始化方法来初始化它提供的属性值:
- (id) initWithName:(NSString *)name andAge:(int)age andNo:(int)no {
        if (self = [super initWithName:name andAge:age]) {     // 调用父类的初始化方法
                _no = no;
        }
        return self;
}
这样写最好父类的成员变量就使用父类的方法来给它初始化自己的成员变量自己初始化.
这样的话如果父类的init方法对成员变量的初始值有特别的设置或者筛选那么子类的初始化方法里就不需要再写一遍直接使用父类的初始化方法安全又方便.
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值