黑马程序员——ObjC基础—对象的其他要点

----------- Java 培训Android 培训IOS 培训.Net 培训、期待与您交流!------------ 
在前面的学习中有一些零星的要点,总结在这里。

1、匿名对象
    [NSObject new];
上面的代码定义了一个匿名的对象,也就是说,没有指针指向这个对象,这种对象只有在创建的时候能进行操作,之后则无法调用,一般不建议使用,只做简单的了解。

2、数据监听
我们举一个常见的统计分数的例子,我们要求创建一个分数对象,包含数学、语文、英语分数等属性,以及总分和平均分属性,总分和平均分显然是通过各门课程的分数直接求出来的,不应该另行设置,我们看看该如何实现:
@interface Score : NSObject

// 注意这里的nonatomic不能省略,因为我们打破了自动线程管理的规范
@property (nonatomic) int mathScore;
@property (nonatomic) int chineseScore;
@property (nonatomic) int englishScore;

@property  (nonatomic) int totalScore;
@property (nonatomic) int averageScore;

@end

@implementation Score

// set方法重写(取代自动生成的set方法)
- (void)setMathScore:(int)mathScore{
    _mathScore = mathScore;
    _totalScore = _mathScore + _chineseScore + _englishScore; // 监听
    _averageScore = _totalScore / 3; // 监听
}
- (void)setChineseScore:(int)chineseScore{
    _chineseScore = chineseScore;
    _totalScore = _mathScore + _chineseScore + _englishScore; // 监听
    _averageScore = _totalScore / 3; // 监听
}

- (void)setEnglishScore:(int)englishScore{
    _englishScore = englishScore;
    _totalScore = _mathScore + _chineseScore + _englishScore; // 监听
    _averageScore = _totalScore / 3; // 监听
}

@end


int main(){
    
    Score *s = [Score new]; // 创建新分数对象
    s.mathScore = 80; // 赋值(每赋值一次,总分和均分都会计算一次)
    s.chineseScore = 90; // 赋值(每赋值一次,总分和均分都会计算一次)
    s.englishScore = 95; // 赋值(每赋值一次,总分和均分都会计算一次)
    
    NSLog(@"totalScore is %d", s.totalScore); // 总分直接输出
    NSLog(@"averageScore is %d", s.averageScore); // 平均分直接输出

    return 0;
}
这种在参数设置的过程中,添加的代码,实际上实现了监听参数变化的效果,类似这样的处理,我们称之为监听。

3、对象里的对象
我们知道,一个对象内部可以有多个属性,属性可不可以是对象呢?这当然也是可以的,注意,当属性为对象的时候,实际上这个属性是一个指向另一个对象的指针。(其实,前面用到的NSString类型的字符串就是一个对象),我们来看下面的例子:
// Dog 类
@interface Dog : NSObject
@property NSString *name;
@end
@implementation Dog
@end

// Person 类
@interface Person : NSObject
@property NSString *name;
@property Dog *dog; // 狗作为人的一个参数
@end
@implementation Person
@end

int main(){
    
    Dog *d = [Dog new]; //创建狗对象
    d.name = @"Wowo";
    
    Person *p = [Person new]; // 创建人对象
    p.name = @"xiaoming";
    p.dog = d; // 人对象获取狗对象
    
    // 输出(注意d的属性是通过p取得的)
    NSLog(@"I am %@, I have a dog named %@!", p.name, p.dog.name);
    
    return 0;
}

4、组合
当两个类之间没有什么逻辑关系,但是又有相同的属性时,我们一般是采用组合的方式来设计,相同的部分,我们提取为一个类,然后在另一个类里,把这个类当成一个属性。这和上面的例子的实现基本一致。
// Score 类
@interface Score : NSObject
@property int chineseScore;
@property int englishScore;
@property int mathScore;
@end
@implementation Score
@end

// Student 类
@interface Student : NSObject
@property NSString *name;
@property int number;
@property Score *score; // 分数类作为学生的一个属性(组合)
@end
@implementation Student
@end
这样一来,学生对象就有了分数对象里面的属性。只不过操作的时候,要多一个点语法操作。

5、self和super
self在OC中是一个特殊的指针,用于表示当前的对象,而super是一个编译器特定,他指向当前类的父类。
// Animal 类(父类)
@interface Animal : NSObject
@property int age;
- (void)showDetail;
@end
@implementation Animal
- (void)showDetail{
    NSLog(@"Age is %d", self.age); // 通过self操作属性
}
@end

// Dog 类(子类)
@interface Dog : Animal
@property NSString *name;
@end

@implementation Dog
- (void)showDetail{ // 重写父类中存在的方法
    NSLog(@"Name is %@", self.name); // 通过self操作属性
    [super showDetail]; // 通过super访问父类方法
}
@end

// 主函数
int main(){
    
    Dog *d = [Dog new];
    d.name = @"Wowo";
    d.age = 3;
    [d showDetail]; // 该show方法将会同时调用父类的show方法
    
    return 0;
}
输出如下:
2015-02-13 13:19:05.447 Study[21944:303] Name is Wowo
2015-02-13 13:19:05.450 Study[21944:303] Age is 3

6、重写
在上面的例子中已经出现了方法的重写,这种在父类中存在的方法,如果我们不希望子类继承,可以在子类中重写方法,只要和父类中的方法名称参数都一样即可,注意,不需要重新声明方法。在某个继承链中,当每一级别的类里都有某个方法时,方法的调用是从当前对象开始往上追溯的,遇到的第一个为执行的方法。

7、多态
定义对象时,类型指定为父类及以上的情况,可实现对象的多态。我们通过一个简单的例子来理解这个概念:
定义一个人的类,有一个喂食的方法,可以喂狗和猫东西吃。在实际操作中,我们可以抽象出动物的概念,猫和狗都继承自动物,我们只要能给动物喂食,相应的也能给猫和狗喂食,猫和狗的类中也可以重写出个性化的处理,不会出现干扰。
我们来看看怎么实现:
// Animal 类
@interface Animal : NSObject
- (void)eat;
@end
@implementation Animal
- (void)eat{ // eat 方法
    NSLog(@"Animal eat!");
}
@end

// Dog 类 --> Animal 类
@interface Dog : Animal
@end
@implementation Dog
- (void)eat{ // 重写
    NSLog(@"Dog eats!");
}
@end

// Cat 类 --> Animal 类
@interface Cat : Animal
@end
@implementation Cat
- (void)eat{ // 重写
    NSLog(@"Cat eats!");
}
@end

// Person 类
@interface Person : NSObject
- (void)feedAnimal:(Animal*)animal;
@end
@implementation Person
- (void)feedAnimal:(Animal*)animal{
    NSLog(@"Feed a %@", animal); // 输出的是具体对象
    [animal eat]; // 先在具体对象内找方法
}
@end


// 主函数
int main(){
    
    Person *p = [Person new];
    Cat *c = [Cat new];
    Dog *d = [Dog new];
    
    [p feedAnimal:c]; // 可以对多种对象进行操作
    [p feedAnimal:d]; // 可以对多种对象进行操作
    
    return 0;
}
通过上面的代码,我们可以发现,定义的方法可以接收多种对象,而且每个对象能够做出不一样的处理,来看看输出结果:
2015-02-13 18:05:11.226 Study[22236:303] Feed a <Cat: 0x1002026d0>
2015-02-13 18:05:11.229 Study[22236:303] Cat eats!
2015-02-13 18:05:11.230 Study[22236:303] Feed a <Dog: 0x100202850>
2015-02-13 18:05:11.231 Study[22236:303] Dog eats!







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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值