------- android培训、java培训、IOS培训、期待与您交流! ----------
前言:在学完OC的基本语法与核心语法后,我们发现OC的基本学习内容都是语法和用法,以及相应地应用. 我们知道, 作
为面向过程的C语言,经常要深入到具体的实现过程中去考虑设计功能的实现,而OC作为面向对象语言,它是专门体现面
向对象思想的,又是如何在实际开发应用中体现出来的呢,我们这里引入一个OC类的设计习题
正文:
OC开发技巧部分—习题06:
// 设计一个类circle,用来表示二维平面中得圆
// 1>属性
// double radius (半径)
// Point2D *point (圆心)
// 2>方法
// 属性相应地set和get方法
// 设计一个对象判断跟其他圆是否重叠(重叠返回YES,否则返回NO)
//设计一个类方法判断两个圆是否重叠(重叠返回YES,否则返回NO)
我们看到,在这里,需要设计的类circle里面还包含了一个类point,这种一个类中包含了多个类成员变量的情况也是我们今
后开发所经常要遇到的,那么在这个简单地单类包含情况下,我们的类设计该如何实现了
为了实现所需类Circle的需求,我们首先需要设计好一个point类:
这个类应该拥有如下属性:
//1>属性
//double x
//double y
// 2>方法
// 属性相应的set和get方法
// 设计一个对象方法同时设置x和y
// 设计一个对象方法计算跟其他点得距离
//设计一个类方法计算两个点之间的距离
我们根据所需,根据我们在OC基本语法和核心语法里所学习的内容对point进行类设计
#import <Foundation/Foundation.h>
#import <math.h>
@interface Point2D :NSObject
{
double _x;
double _y;
}
// x值的getter和setter
- (void)setX:(double)x;
- (double)x;
// y值的getter和setter
- (void)setY:(double)y;
- (double)y;
// 设计一个对象方法同时设置x和y
- (void)setX:(double)x andY:(double)y;
// 设计一个对象方法计算跟其他点得距离
- (double)distanceWithOther:(Point2D *)other;
// 设计一个类方法计算两个点之间的距离
+ (double)distanceBetweenPoint1:(Point2D *)Point1 andPoint2:(Point2D *)Point2;
@end
@implementation Point2D
// x值的getter和setter
- (void)setX:(double)x
{
_x = x;
}
- (double)x
{
return_x;
}
// x值的getter和setter
- (void)setY:(double)y
{
_y = y;
}
- (double)y
{
return_y;
}
// 设计一个对象方法同时设置x和y
- (void)setX:(double)x andY:(double)y
{
// _x = x;
// _y = y;
//建议这样写,因为可能会有过滤
[selfsetX:x];
[selfsetY:y];
}
// 设计一个对象方法计算跟其他点的距离
- (double)distanceWithOther:(Point2D *)other
{
return [Point2DdistanceBetweenPoint1:selfandPoint2:other];
}
// 设计一个类方法计算两个点之间的距离
+ (double)distanceBetweenPoint1:(Point2D *)Point1 andPoint2:(Point2D *)Point2
{
double xDelta = [Point2x] - [Point1x];
double xDeltaPF =pow(xDelta,2);
double yDelta = [Point2y] - [Point1y];
double yDeltaPF =pow(yDelta,2);
returnsqrt(xDeltaPF + yDeltaPF);
}
@end
点设计这部分最值得注意的就是两个计算方法是可以相互调用的,因此只需要写一个方法的实现即可,避免重复累赘代
码
int main()
{
Point2D *p1 = [Point2Dnew];
Point2D *p2 = [Point2Dnew];
[p1 setX:0.0 andY:1.0];
[p2 setX:3.0 andY:5.0];
double dis = [Point2DdistanceBetweenPoint1:p1andPoint2:p2];
NSLog(@"%f",dis);
double dis2 = [p1distanceWithOther:p2];
NSLog(@"%f",dis2);
return0;
}
建立一个主函数对这个类以及类的实现进行测试,满足要求,那么这个point类就作为一个独立的对象以及实现好了
接下来完成Circle类的设计
圆
@interface Circle :NSObject
{
// double radius (半径)
double _radius;
// Point2D *point (圆心)
Point2D *_point;
}
//半径的setter和getter
- (void)setRadius:(double)radius;
- (double)radius;
//圆心的setter和getter
- (void)setPoint:(Point2D *)point;
- (Point2D *)point;
//判定是否重叠
//返回值是bool类型的,方法名一般都以is开头
- (BOOL)isInteractWithOther:(Circle *)other;
+ (BOOL)isInteractBetweenCircle1:(Circle *)c1 andCircle2:(Circle *)c2;
@end
@implementation Circle
//半径的setter和getter
- (void)setRadius:(double)radius
{
_radius = radius;
}
- (double)radius
{
return_radius;
}
//圆心的setter和getter
- (void)setPoint:(Point2D *)point
{
_point = point;
}
- (Point2D *)point
{
return_point;
}
- (BOOL)isInteractWithOther:(Circle *)other;
{
//如果圆心距离<半径和.重叠
Point2D *p1 = [selfpoint];
Point2D *p2 = [otherpoint];
//圆心距离
double distance = [p1distanceWithOther:p2];
//半径和
double radiusSum = [selfradius] + [otherradius];
//判断后返回值
return distance < radiusSum;
}
+ (BOOL)isInteractBetweenCircle1:(Circle *)c1 andCircle2:(Circle *)c2
{
return [c1isInteractWithOther: c2];
}
@end
Circle类的设计实现,除了关于方法实现上与point一样根据相互调用来避免重复累赘代码这点需要注意外,最重要的一
点,就是对于成员变量point的包含,以及它的set和get方法.在Circle类的设计过程中,我们把point当做是一个普通的成员
变量,除了类型不同,与普通的基本数据类型变量没有任何区别,这也是OC的面向对象思想的体现之一.OC并不要求知道
类中的包含类是如何实现的,各个功能的实现封装在不同的对象中,对于每一个对象,其他所有的对象都是封装好的只有
功能属性的简单对象.
建立新的主函数,对我们实现好的类设计进行测试
int main()
{
//圆对象c1
Circle *c1 = [Circlenew];
//创建圆心对象(点对象)
Point2D *p1 = [Point2Dnew];
[p1 setX:10 andY:15];
//先设置圆心
[c1 setPoint: p1];
[[c1 point] setX:15];
//半径
[c1 setRadius:2];
//圆对象c2
Circle *c2 = [Circlenew];
//创建圆心对象(点对象)
Point2D *p2 = [Point2Dnew];
[p2 setX:12 andY:19];
//先设置圆心
[c2 setPoint:p2];
//半径
[c2 setRadius:6];
BOOL b0 =[c1isInteractWithOther:c2];
BOOL b1 =[CircleisInteractBetweenCircle1:c1andCircle2:c2];
NSLog(@"%d",b0);
NSLog(@"%d",b1);
return0;
}
满足要求.这个练习充分体现了OC中类的封装和调用关系
而在实际开发过程中,一旦像这样需要包含和引用的类超过一定的数量,写在同一个文件中,就会写得相当复杂,降低程序
的可读性,因此我们需要像c语言里那样对不同功能的文件进行独立封装.
对圆,点题的类进行独立封装
1.Point2D.m :Point2D这个类的声明与实现 编译成功->Point2D.o文件(然而没有主函数)->无法生产可执行文件
2.Circle.m : Circle这个类的声明和实现 (+Point2D的声明和实现) 编译不成功(缺乏Point*_point的说明) ->预处理位置
加上#import "Point2D.m" ->编译成功->Circle.o文件(然而仍然没有主函数) ->无法产生可执行文件
3.main.m :main函数 预处理加上#import"Point2D.m"和"Circle.m"
这样很像c语言的多文件包含思想,然而实际中并不是这样做,因为Xcode在运行时会自动加载当前文件夹里所有的.m文
件,所以如果这样做会有很多的重复,由于重复定义而报错,那么该怎么办呢?
为了解决这个问题,引入c语言中的头文件概念,预处理里只引入.h文件,严禁引入.c和.m文件等源文件
把类同函数那样分拆成声明和实现,声明放在.h文件中,实现放在.m文件中,Point2D.m文件中加入预处理
#import"Point2D.h" Circle.h的声明中加入预处理Point2D.h, Circle.m 文件中加入预处理Circle.h. 而主函数中加入预处
理两个头文件.
定义一个类分为2个文件:.h声明文件, .m实现问价
.h 成员变量,方法的声明
.m 方法的实现
如果想使用某一个类,只需要#import类的.h文件即可