一、特性一:封装
1、封装的概念
封装是指把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
2、set方法和get方法
(1)set方法和get方法的使用场合
由于@public的成员可以被任何对象访问,存在安全隐患,所以应该使用set方法和get方法来管理成员的访问,同时也可以对数据进行过滤
(2)set方法
作用:设置成员变量并并对值进行过滤。
命名规范:方法都是以set开头,后面跟上成员变量名,成员变量名的首字母必须大写形参名称不能跟成员变量同名。
(3)get方法
作用:返回对象内部的成员变量。
命名规范:get方法的名称一般跟成员变量同名。
(4)成员变量的命名规范
成员变量都以下划线 _ 开头,不仅可以跟get方法的名称区分开,也可以跟其他局部变量区分开,以下划线开头的变量,肯定是成员变量。
(5)封装的好处
a、过滤不合理的值
b、屏蔽内部的赋值过程
c、让外界不必关注内部的细节
代码示例:
#import <Foundation/Foundation.h>
//用性别定义了了一个性别属性
typedef enum{
SexMan,
SexWoman
}Sex;
@interface Student : NSObject
{
//成员变量以下划线_开头,可以RNA过成员变量和get方法名称区别开来,可以跟局部变量区分开
int _no;
Sex _sex;
}
//sex的set和get方法
- (void) setSex : (Sex) sex;
- (Sex) sex;
//no的set和get方法
- (void) setNo : (int) no;
- (int) no;
@end
@implementation Student
//sex的set和get方法
- (void) setSex : (Sex) sex
{
_sex = sex;
}
- (Sex) sex
{
return _sex;
}
//no的set和get方法
- (void) setNo : (int) no
{
_no = no;
}
- (int) no
{
return _no;
}
@end
int main()
{
Student *stu = [Student new];
[stu setSex:SexMan];
[stu setNo:10];
NSLog(@"%d",[stu sex]);
NSLog(@"%d",[stu no]);
return 0;
}
@end
3、类方法
(1)基本概念
类的方法可以用类来直接调用(类本身会在内存中占据存储空间,里面有类\对象方法列表)
(2)类方法和对象方法对比
a、对象方法:以减号“-”开头,只有对象才调用,没有对象这个方法根本不可能被执行,对象方法能访问实例变量(成员变量)。
b、类方法:以加号“+”开头,只能用类名调用,对象不能调用,类方法中不能访问实例变量(成员变量),当不需要访问成员变量的时候,尽量用类方法,效率高。
c、类方法和对象方法可以同名。
代码示例:
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
int age;
}
//类方法都是以+开头
+ (void) printClassName;
//对象方法,以-开头
- (void) test;
+ (void) test;
@end
/*
经典报错: error:instance variable 'age' accessed in class method
实例变量age不能在方法中访问
类中的方法不能访问成员变量(实例变量)
*/
@implementation Person
//类方法都是以+开头
+ (void) printClassName
{
NSLog(@"Person");
}
//对象方法,以-开头
- (void) test
{
NSLog(@"111-%d",age);
}
+(void) test
{
NSLog(@"333");
}
@end
int main()
{
[Person printClassName];
[Person test];
Person *p = [Person new];
[p test];
/*
[p printClassName];
报错:unrecognized selector sent to instance 0x7fa520c0b370
系统会认为调用的是对象方法printClassName
*/
return 0;
}
4、self关键字
(1)self
self是指当前的调用者,如果在对象中,self指的是该对象,如果在类中,self指的是该类,用self来访问成员变量,可以区分同名的局部变量。
(2)使用细节
在所有的OC方法中(对象方法\类方法)都可以使用self,但不能在函数中使用。
(3)作用
使用 "self->成员变量名" 访问当前方法调用的成员变量,使用 "[self 方法名];" 来调用方法(对象方法\类方法)
如在set方法和get方法中调用成员变量:
- (void) setAge:(int) age
{
self->_age=age;
}
- (int) age
{
return self->_age;
}
- (void) test
{
//self:指向了调用者,代表者当时对象
int _age = 20;
NSLog(@"Person的年龄是%d岁",self->_age);
}
@end
调用方法:
#import <Foundation/Foundation.h>
@interface Dog : NSObject
- (void) bark;
- (void) run;
@end
@implementation Dog
- (void) bark
{
NSLog(@"wwwww");
}
- (void) run
{
[self bark];
NSLog(@"run");
}
@end
int main()
{
Dog *d = [Dog new];
[d run];
return 0;
}
(4)常见错误
a、用self去调用函数
b、类方法中用self调用对象方法,对象方法中用self调用类方法
c、self死循环:在类方法中或对象方法中调用自己
二、特性二:继承
1、继承的概念
继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
2、继承的基本用法
代码示例:
#import <Foundation/Foundation.h>
/*父类Animal的声明*/
@interface Animal : NSObject
{
int _age;
double _weight;
}
- (void) setAge : (int) age;
- (int) age;
- (void) setWeight : (double) weight;
- (double) weight;
@end
/*Animal的实现*/
@implementation Animal
- (void) setAge : (int) age
{
_age = age;
}
- (int) age
{
return _age;
}
- (void) setWeight : (double) weight
{
_weight = weight;
}
- (double) weight
{
return _weight;
}
@end
// : Animal =》继承了Animal,相当于拥有了Animal里面的所有成员变量和方法
// Anmial为父类,dog为子类
/*子类Dog,继承类Animal,拥有该类的所有成员和方法*/
@interface Dog : Animal
@end
@implementation Dog
@end
/*子类Cat*/
@interface Cat : Animal
@end
@implementation Cat
@end
int main()
{
Dog *d = [Dog new];
// Dog类中没有setAge的方法,程序会自动到它的父类中去寻找调用
[d setAge:10];
NSLog(@"age=%d",[d age]);
return 0;
}
总结:
(1)子类方法和属性的访问过程:优先访问子类,如果子类没有则去父类中寻找
(2)父类被继承了还是能够照常使用
(3)NSObject是全部OC类的最终父类,它包含类一些常用的方,比如 new
(4)每一个类中都有一个superClass的指针,该指针指向它的父类
3、继承的专业术语
(1)父类\超类 superclass
(2)子类 subclass\subclasses
4、继承的细节
(1)OC的继承是单继承,一个类只能又一个父类
(2)子类和父类不能有相同的成员变量
(3)方法的重写
代码示例:
/*
重写:子类重新实现父类中的某个方法,覆盖父类以前的做法
*/
#import <Foundation/Foundation.h>
//父类:Person
@interface Person : NSObject
{
int _age;
}
- (void) setAge : (int) age;
- (int) age;
- (void) run;
+ (void) test;
@end
@implementation Person
- (void) setAge : (int) age
{
_age = age;
}
- (int) age
{
return _age;
}
- (void) run
{
NSLog(@"person--跑");
}
+ (void) test
{
NSLog(@"person+test");
}
@end
// 不允许子类和父类拥有相同名称的成员变量
//子类:Student
@interface Student : Person
{
int _no;
}
//类中的方法
+ (void) test2;
@end
@implementation Student
+ (void) test2
{
//调用该类的test1方法,查找顺序为从子类再到父类
[self test];
}
@end
int main()
{
[Student test2];
//[Student new]是调用Student中的new方法,Student中没有就到父类NSObject中查找
Student *s = [Student new];
[s run];
return 0;
}
5、super关键字
可以在子类中通过super关键字来调用父类的对象方法和类方法
代码示例:
#import <Foundation/Foundation.h>
@interface Zoombie : NSObject
- (void) walk;
+ (void) test;
- (void) test;
@end
@implementation Zoombie
- (void) walk
{
NSLog(@"往前挪两步***");
}
+ (void) test
{
NSLog(@"ZoomBie+test");
}
- (void) test
{
NSLog(@"Zoombie-test");
}
@end
@interface JumpZoombie : Zoombie
+ (void) haha;
- (void) haha2;
@end
@implementation JumpZoombie
+ (void) haha
{
//调用的是父类中的类方法
[super test];
}
- (void) haha2
{
//调用的是父类中的对象方法
[super test];
}
//重写父类中的方法
- (void) walk
{
NSLog(@"跳两下");
[super walk];
}
@end
int main()
{
[JumpZoombie haha];
JumpZoombie *jz = [JumpZoombie new];
[jz haha2];
return 0;
}
6、继承的好处
(1)在不改变原来模型的基础上,拓充方法
(2)建立了类与类之间的联系
(3)抽取了公共代码使代码更加简练
7、继承的缺点
就是类之间的耦合性太强,不利于维护。
8、继承的使用场合
如果多个类具有相同的属性就可以抽取出一个父类
9、继承和组合
组合是指将其他类的对象作为自己的成员变量定义到自己的类中。
代码示例:
@interface Score : NSObject
{
int _cScore;
int _ocScore;
}
@end
@implementation Score
@end
@interface Student : NSObject
{
//组合
Score *_score;
int _age;
}
@end
@implementation Student
@end
三、特性三:多态
1、多态的概念
多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。即允许将子类类型的指针赋值给父类类型的指针。
2、多态的体现
例如有一个类Student继承自Person,那么就可以把子类对象赋值给父类指针,父类指针可以访问对应的属性和方法。
代码示例:
Person *p = [Student new];
p->age = 100;
[p walk];
3、多态的好处
可以用父类接收参数,节省代码
代码示例:
#import <Foundation/Foundation.h>
/*
有继承才有多态
*/
//动物
@interface Animal : NSObject
- (void) eat;
@end
@implementation Animal
- (void) eat
{
NSLog(@"Animal-吃东西--");
}
@end
//狗
@interface Dog : Animal
- (void) run;
@end
@implementation Dog
- (void) run
{
NSLog(@"Dog-跑");
}
//重写父类方法
- (void) eat
{
NSLog(@"Dog-吃东西--") ;
}
@end
//猫
@interface Cat : Animal
@end
@implementation Cat
- (void) eat
{
NSLog(@"Cat--吃东西--");
}
@end
//参数中使用的是父类类型,可以传入父类和子类对象——多态
void feed(Animal *a)
{
[a eat];
}
int main()
{
Animal *aa = [Dog new];
[aa eat]; //调用的是子类中的eat方法,多态中父类不能调用子类的方法
//将Animal类型为Dog类型
Dog *dd = (Dog *) aa;
[dd run];
Dog *d = [Dog new];
[d run];
//喂动物
Animal *a = [Animal new];
feed(a);
//喂狗
feed(d);
//喂猫
Cat *c = [Cat new];
feed(c);
return 0;
}
4、多态的局限性
不能访问子类的属性(可以考虑强制转换)
5、多态的细节
动态绑定:在运行时根据对象的类型确定动态调用的方法
代码示例:
Animal *aa = [Dog new]; Dog *dd = (Dog *) aa; [dd run];
四、NSString 1、以面向对象的方法快速创建字符串
NSStirng *str = @“Hello”;
2、使用%@输出字符串
NSString *name = @”mj”;
NSLog(@“我的名字是%@”, name);
代码示例:
#import <Foundation/Foundation.h>
int main()
{
int age = 15;
int no = 5;
NSString *name = @"哈哈jack";
//length方法算的是字数
int size = (int)[name length];
NSLog(@"---size---%d",size);
//创建oc字符串的另一种方式,OC字符串中的占位符是%@
NSString *newStr = [NSString stringWithFormat:@"my age is %d and no is %d and name is %@",age ,no ,name];
//length方法返回的是unsigned long类型
NSLog(@"----%ld",[newStr length]);
return 0;
}