Objective-C 学习笔记(Day 3,下)
———————————————————————————————————————————
封装概念及其原理
一个Gun类的例子来详细说明这一环节:
#import <Foundation/Foundation.h>
@interface Gun : NSObject
{
@public
int _bulletCount;
}
-(void)shoot;//这是射击的方法,前提是有子弹(子弹>=0),子弹数目<0则没有意义,我们要让方法整体符合逻辑。
-(void)setGunBullet:(int)bullet;//我们虽然可以在shoot方法中将子弹数目的判定写上,但是这样做有一点点不符合常理。这是因为如果我们只写一个shoot方法,而我们传的值为-3,然后让shoot去接收-3这个值判断,如果在shoot方法内先打印一下子弹数,很明显子弹数为-3是不对的,是不安全的。我们根本不需要去接收这个不正确的值,接收了说明不严谨。所以说我们需要一个方法去预处理一下子弹的个数,这也是体现的封装的思想。
@end
@implementation Gun
-(void)shoot
{
if (_bulletCount>0) {
_bulletCount--;
NSLog(@"tututu ...");
}
else
{
NSLog(@"No bullet!");
}
}
-(void)setGunBullet:(int)bullet
//在setGunBullet:方法中,我们先接收输入的值判断,然后再将处理过的值传给实例变量_bulletCount,处理之后的值肯定是>=0的,符合了子弹数目的逻辑(有子弹>0,没有子弹=0)
{
if (bullet>0) {
_bulletCount=bullet;
}
else
{
_bulletCount=0;
}
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Gun *gun=[[Gun alloc]init];
[gun setGunBullet:3];
[gun shoot];
[gun shoot];
[gun shoot];
[gun shoot];
[gun shoot];
}
return 0;
}
———————————————————————————————————————————
封装的实现步骤
★★★这一部分是重点哦!重点记忆!★★★
★定义 设置实例变量(setter)方法 和 访问实例变量(setter)方法,在这里我们可以通俗的将set记为设置成员变量的值,将get记为获取成员变量的值。
(这里的实例变量就是声明类的时候的属性成员变量,叫法很多)
(1)setter方法(设置器)
在开发过程中,出于安全性的考虑,我们不会在成员变量名的前面使用 @public 、@protected 等关键字进行修饰,而是使用set方法来为对象提供成员变量的值,在set方法的内部也对一些不合理的赋值进行过滤。
set方法的作用:为外界提供一个设置成员变量值的方法。
★set方法的命名规范:
①set方法一定是一个对象方法( - 号开头)
②set方法一定 没有返回值(返回值为void类型)
③set方法的方法名必须set开头
④set方法的方法名在 写完set开头 后应该跟成员变量名去掉下划线后首字母大写的单词
(如:成员变量名为 _name,那么set方法名为 setName)
⑤set方法必须有参数,而且参数的类型要和该成员变量的类型保持一致
⑥参数的参数名是成员变量名去掉下划线后的单词
(如:成员变量名为 _age,那么set方法的参数名为 age。苹果官方推荐 成员变量名 前面加下划线 “ _ ” 以示区分)
⑦形参名不能和成员变量名同名(这一条和第⑥条差不多)
⑧set方法实现一定要通过形参给成员变量(实例变量)赋值(这也是set方法的作用~)
(2)getter方法(访问器)
get方法的作用:为外界提供一个获取(返回、得到)成员变量值的方法
★get方法的命名规范:
①get方法一定是一个对象方法 ( - 号开头)
②get方法一定 有返回值,且返回值类型和成员变量的类型一致
③get方法的方法名是去掉下划线的成员变量名
(如:成员变量名为 _name,那么get方法名为name,★注意没有get开头★,这里是和java不一样的)
④get方法一定没有参数
⑤get方法实现一定是返回(获取)成员变量(实例对象)的值
下面一个Person类的例子向大家详细介绍set、get方法的定义与使用:
#import <Foundation/Foundation.h>
typedef enum {kSexMan,kSexWoman,kSexYao}Sex;
@interface Person : NSObject
{
NSString *_name;
Sex _sex;
int _age;
float _height;
}
//以后设置(赋值)_name、_sex 等等成员变量(实例变量)的值,都统一使用其set方法
//_name的set方法
-(void)setName:(NSString *)name;
//_sex的set方法
-(void)setSex:(Sex)sex;
//_age的set方法
-(void)setAge:(int)age;
//_height的set方法
-(void)setHeight:(float)height;
//以后访问(获取)_name、_sex 等等成员变量(实例变量)的值,都统一使用其get方法
//_name的get方法
-(NSString *)name;
//_sex的get方法
-(Sex)sex;
//_age的get方法
-(int)age;
//_height的get方法
-(float)height;
@end
@implementation Person
//-----------------------set 方法的实现-----------------------
//_name的set方法
-(void)setName:(NSString *)name
{
_name=name;
}
//_sex的set方法
-(void)setSex:(Sex)sex
{
_sex=sex;
}
//_age的set方法
-(void)setAge:(int)age
{
_age=age;
}
//_height的set方法
-(void)setHeight:(float)height
{
_height=height;
}
//-----------------------get 方法的实现-----------------------
//_name的get方法
-(NSString *)name
{
return _name;
}
//_sex的get方法
-(Sex)sex
{
return _sex;
}
//_age的get方法
-(int)age
{
return _age;
}
//_height的get方法
-(float)height
{
return _height;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p=[Person new];
// 以后我们对实例变量操作都要用set、get方法,封装之后安全性高
[p setName:@"wang"];//调用_name的set方法,为其实例变量赋值
NSLog(@"name:%@",[p name]);//调用_name的get方法,获取返回值,并打印出来
[p setAge:21];
NSLog(@"name:%d",[p age]);
[p setSex:kSexMan];
NSLog(@"name:%d",[p sex]);
[p setHeight:179.5];
NSLog(@"name:%.2f",[p height]);
}
return 0;
}
———————————————————————————————————————————
封装的应用案例(股票k线计算)
#import <Foundation/Foundation.h>
@interface KLine : NSObject
{
float _minPrice;//最低股价,可读(get)写(set)
float _maxPrice;//最高股价,可读写
float _avPrice;//平均股价,只读(get)
}
-(void)setMinPrice:(float)minPrice;
-(float)minPrice;
-(void)setMaxPrice:(float)maxPrice;
-(float)maxPrice;
-(float)avPrice;
@end
@implementation KLine
-(void)setMinPrice:(float)minPrice
{
_minPrice=minPrice;
_avPrice=(_maxPrice+_minPrice)/2;//我们在_minPrice和_maxPrice的set方法中都加了一句计算平均值的语句,这样的话很好的向大家展示出只要两个值的其中一个发生了改变,平均值就立马发生变化,而不是等到我们读_avPrice的时候才发生变化。这样的写法才更符合逻辑
}
-(float)minPrice
{
return _minPrice;
}
-(void)setMaxPrice:(float)maxPrice
{
_maxPrice=maxPrice;
_avPrice=(_maxPrice+_minPrice)/2;
}
-(float)maxPrice
{
return _maxPrice;
}
-(float)avPrice
{
// _avPrice=(_maxPrice+_minPrice)/2;
// 我们完全可以直接在实例变量_avPrice的get方法内写上面这一句,这样只要_minPrice或者_maxPrice发生了变化,那么_avPrice的值就发生变化,但是这样意义体现的不是很明确。
return _avPrice;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
KLine *kline=[KLine new];
[kline setMaxPrice:55.9];
[kline setMinPrice:23.8];
NSLog(@"avPrice:%.2f",[kline avPrice]);
}
return 0;
}
我觉得上面这个程序需要着重注意的地方有两点:
①可读写的意思:读(get),写(set)
②注意在取平均值的时候,一定要符合逻辑性,结果可能都是一个样子,但是怎么出来的结果要格外严谨!
———————————————————————————————————————————
依赖关系
下面通过一个简短的小程序来解释一下这一部分。
#import <Foundation/Foundation.h>
@interface IPhone : NSObject
{
NSString *_phoneNum;
}
-(void)setPhoneNum:(NSString *)phoneNum;
-(void)callPhone;
-(void)sendMessage;
@end
@interface Girl : NSObject
-(void)callPhoneToTuhao:(IPhone *)phone;
-(void)sendMessageToTuhao:(IPhone *)phone;
@end
@implementation IPhone
-(void)setPhoneNum:(NSString *)phoneNum
{
_phoneNum=phoneNum;
}
-(void)callPhone
{
NSLog(@"给土豪打电话,电话为:%@",_phoneNum);
}
-(void)sendMessage
{
NSLog(@"给土豪发短信,电话为:%@",_phoneNum);
}
@end
@implementation Girl
-(void)callPhoneToTuhao:(IPhone *)phone
{
[phone setPhoneNum:@"18363861160"];
[phone callPhone];
}
-(void)sendMessageToTuhao:(IPhone *)phone
{
[phone setPhoneNum:@"18363861160"];
[phone sendMessage];
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
//有这么两个类:Girl和IPhone
//美女要通过电话给土豪联系,所以说美女依赖于电话,电话是美女打电话时的一个参数!
IPhone *ip7=[IPhone new];
Girl *girl=[Girl new];
[girl callPhoneToTuhao:ip7];
[girl sendMessageToTuhao:ip7];
}
return 0;
}
//ip7 girl
//A对象 作为 B对象 的局部变量或者是方法形参时,B依赖于A,如刚刚的我们写的程序:
//[girl callPhoneToTuhao:ip7] girl对象依赖于ip7对象
———————————————————————————————————————————
关联关系
下面通过一个简短的小程序来解释一下这一部分。
#import <Foundation/Foundation.h>
@interface IPad : NSObject
{
NSString *_name;
}
-(void)setName:(NSString *)name;
-(void)showMusic;
-(void)showMovie;
-(void)playGames;
@end
@interface Person : NSObject
{
NSString *_name;
IPad *_ipad;
}
-(void)setName:(NSString *)name;
-(void)setIPad:(IPad *)ipad;
-(void)listenMusic:(IPad *)ipad;
@end
@implementation IPad
-(void)setName:(NSString *)name
{
_name=name;
}
-(void)showMusic
{
NSLog(@"正在用%@播放音乐!",_name);
}
-(void)showMovie
{
NSLog(@"正在用%@看电影!",_name);
}
-(void)playGames
{
NSLog(@"正在用%@打游戏!",_name);
}
@end
@implementation Person
-(void)setName:(NSString *)name
{
_name=name;
}
-(void)setIPad:(IPad *)ipad
{
_ipad=ipad;
}
-(void)listenMusic:(IPad *)ipad//在listenMusic方法内部我只写了一个showMusic方法,剩下的读者可以自行添加。
{
[ipad showMusic];
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p=[Person new];
IPad *i=[IPad new];
[i setName:@"ipad123"];
[p setName:@"wangzhongyao"];
[p setIPad:i];
[p listenMusic:i];
}
return 0;
}
这一部分也是很重要的,和依赖关系差不多,经常用到,记住里面类之间是怎么调用的。其实仔细看看就会发现,每个类只管自己的事情,需要什么就去拿什么,一个类需要另一个类就要加上所需的头文件,设置形参啊什么的也都一样,需要就设。慢慢理解,慢慢熟悉整个过程。还有一点,赋值一定要用set方法,记住记住!可能一开始不适应,长时间就好了!上面几个程序没有get方法,因为我们没有用到。
———————————————————————————————————————————
方法重载
★OC里面没有方法重载!
★在OC中方法名是不允许相同的!(与java不一样)
-(void)run:(int)a;
-(void)run:(float)a; //Duplicate declaration of method 'run:' 显然无法同名
注意:
① -(void)run:(int)num1; //方法名是 run:
② -(void)run:(int)num1 and:(float)num2; //方法名是 run: and:
③ -(void)run:(int)num1 : (int)num2 : (int)num3; //方法名是 run: : :
以上三个方法是可以同时存在的,因为方法名不同,尤其要注意第三个。
———————————————————————————————————————————
static关键字的使用
这一部分的知识不是很系统,大家在用到这方面的时候试一试就可以明确了。如果没错误说明可以使用,有错误自然无法使用,希望大家灵活学习。
#import <Foundation/Foundation.h>
static int num2=20;//定义全局变量也是可以的
@interface Dog : NSObject
{
// static int _speed; 这是错误的
//实例变量不能声明为静态
//在C语言中
//没有初始化的静态变量存在BSS段
//如果已经初始化了,存在数据区
}
-(void)run;
@end
@implementation Dog
-(void)run
{
static int num1=10;//定义静态局部变量,是可以的
NSLog(@"num=%d",num1);
num1++;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Dog *dog=[Dog new];
[dog run];
[dog run];
[dog run];
[dog run];//在run方法中num是静态的局部变量,所以每执行一次run方法,num++,num的值会改变。如果不定义成静态的,那么上面多次调用run方法,num值也是不会改变的
NSLog(@"num2=%d",num2);
}
return 0;
}
★总结一下:
①static不能修饰类的方法
②static不能修饰类的实例变量
③static可以修饰全局变量,但是只能在本文件中使用
④static可以修饰局部变量,在方法中可以保存方法上一次的运行结果(局部变量的生命周期延长)
———————————————————————————————————————————
版权声明:本文为博主原创文章,未经博主允许不得转载。
Objective-C 学习笔记(Day 3,下)的更多相关文章
- 学习笔记(1)centos7 下安装nginx
学习笔记(1)centos7 下安装nginx 这里我是通过来自nginx.org的nginx软件包进行安装的. 1.首先为centos设置添加nginx的yum存储库 1.通过vi命令创建一个rep ...
- Web安全学习笔记 SQL注入下
Web安全学习笔记 SQL注入下 繁枝插云欣 --ICML8 SQL注入小技巧 CheatSheet 预编译 参考文章 一点心得 一.SQL注入小技巧 1. 宽字节注入 一般程序员用gbk编码做开发的 ...
- 一起学ASP.NET Core 2.0学习笔记(一): CentOS下 .net core2 sdk nginx、supervisor、mysql环境搭建
作为.neter,看到.net core 2.0的正式发布,心里是有点小激动的,迫不及待的体验了一把,发现速度确实是快了很多,其中也遇到一些小问题,所以整理了一些学习笔记: 阅读目录 环境说明 安装C ...
- CSS学习笔记四:下拉选择框以及其动画特效
以前学的只是了解了css的一些基本属性,在做项目的时候都是直接使用bootstrap响应式来写项目,这样子很方便,很快捷,但是在自己看来还是有一点缺陷的,毕竟,我很多时候不怎么清楚它里面的具体运作.所 ...
- 《JavaScript权威指南》学习笔记 第二天 下好一盘大棋
前段学习js的时候总是零零散散的,以至于很多东西都模棱两可.时间稍微一久,就容易忘记.最主要的原因是这些东西,原来学的时候就不是太懂,以至于和其他知识无法形成记忆链,所以孤零零的知识特别容易忘记.重温 ...
- 【计算机网络】 一个小白的网络层学习笔记:总结下IP,NAT和DHCP
前言:这篇文章是学习网络层协议时候总结的笔记,前面的主要部分介绍的都是IP协议, 后半部分介绍NAT协议和DHCP协议 参考书籍 <计算机网络-自顶向下> 作者 James F ...
- redis学习笔记(一)——windows下redis的安装与配置
前言 很久没有写东西了(.......我的水平就是记个笔记),北漂实习的我,每天晚上回来都不想动,但是做为社会主义接班人的我,还是要时刻给自己充充电,趁着年轻,趁着日渐脱发的脑袋还没有成为" ...
- 程序设计基础·Java学习笔记·面向对象(下)
Java程序设计基础之面向对象(下) (补充了上的一些遗漏的知识,同时加入了自己的笔记的ヾ(•ω•`)o) (至于为什么分P,啊大概是为了自己查笔记方便(?)应该是("` 3′") ...
- Objective -C学习笔记之字典
//字典:(关键字 值) // NSArray *array = [NSArray array];//空数组 // NSDictionary *dictionary = [NSDictionary d ...
- 【Android学习笔记】Mac下Android Studio开发环境搭建
本文由@ray 出品,转载请注明出处. 文章链接:http://www.cnblogs.com/wolfray/p/7829069.html 对于移动端这块,笔者之前一直都是进行iOS开发的,也从来 ...
随机推荐
- 转载 DevOps的基本原则与介绍
转载原地址: http://www.cnblogs.com/wintersun/p/3339047.html DevOps的基本原则与介绍 DevOps这个术语是developer与operatio ...
- Altium Designer快捷键 【worldsing笔记】
Shift + R 切换三种布线模式 (忽略, 避开或推挤) Shift + E 触发电气格点开/关 Shift + B 建立查询 Shift + PgUp 放大到最小的递增 Shift + PgDn ...
- After Android Studio update: Gradle DSL method not found: 'runProguard()'
1 具体报错为: Error:(16, 0) Gradle DSL method not found: 'runProguard()' Possible causes:<ul><li ...
- js避免全局污染
避免声明全局变量,以免发生冲突
- win10 64位安装mysql
原文地址:http://blog.csdn.net/kingyumao/article/details/51925795
- cocos2d-x CCSpriteBatchNode
转自:http://www.cnblogs.com/jiackyan/archive/2013/04/14/3019880.html 1.先说下渲染批次:这是游戏引擎中一个比较重要的优化指标,指的是一 ...
- fb设置viewSourceURL
- 【24】若所有参数皆需类型转换,请为此采用non-members函数
1.令class支持隐式类型转换,往往是个糟糕的主意.但有些情况是合理的,比如数值类型.考虑,有理数Rational有分子,分母两个字段,缺省参数值为0,1.Ration a = 2;我们期望构造一个 ...
- CocoStudio 创建简单UI资源并加入�到project
打开CocoStudio UI编辑器新项目,设置画布480*320, 加入�一个标签和一个button控件 导出项目,生成所须要的资源文件, 拷贝到cocos2dprojectResources文件夹 ...
- [React Fundamentals] Component Lifecycle - Mounting Usage
The previous lesson introduced the React component lifecycle mounting and unmounting. In this lesson ...