- 浏览: 1757984 次
- 性别:
- 来自: 大连
博客专栏
-
Spring数据库访问系列...
浏览量:173784
-
Android学习笔记
浏览量:368239
-
iBatis开发详解
浏览量:189379
-
Objective-C学习...
浏览量:99943
最新评论
-
iLidy:
引用[/c
Hibernate持久化对象的生命周期详解 -
fengzigogo:
您好,有这个项目架构的源码下载地址吗?
一种Java Web应用开发框架的构建(基于Struts2+Spring+FreeMarker)之一 -
spring_springmvc:
可以参考最新的文档:如何在eclipse jee中检出项目并转 ...
用Maven构建Java Web开发环境(Jetty容器)之二 -
springdata_springmvc:
spring mvc demo教程源代码下载,地址:http: ...
Spring 3之MVC & Security简单整合开发(二) -
赵庆辉:
看帖回复是美德,楼主讲的很清晰明了,看了豁然开朗.
Java String对象的经典问题(new String())
接上文
之前定义了矩形类Rectangle,那么我们如果要在桌面上生成这样一个矩形,就需要定位了。为了简便,我们定义桌面的左下角为直角坐标系(笛卡尔坐标系)的原点,横向向右为X轴正向,竖向向上为Y轴正向。那么我们只要确定了矩形的左下角坐标就可以得到矩形的位置了。此时我们就要引入坐标的概念,那么设计XYPoint类,代码如下:
XYPoint.h文件定义了坐标类XYPoint的接口信息,这里面我们使用整数作为坐标,暂时不考虑小数坐标点。那么提供一个方法来设置坐标点,其实现代码为:
就是给属性x和y进行赋值,没有什么可多说的。因为我们要为矩形设置原点坐标(矩形左下角坐标),那么就需要对矩形类Rectangle进行修改,代码如下:
这是类的接口文件,这里面我们使用了@class指令来指定XYPoint类,@class指令可以为我们指定要使用的类,而不用使用import语句,因为这里我们只需要引入XYPoint的定义而已。如果要引用类的实现部分,那么必须使用import语句,@class就不足以提供所需内容了。同时矩形类加入了两个方法,一个是设置原点origin坐标,一个是获取原点坐标,那么矩形类的实现就修改如下:
我们定义私有属性origin来表示坐标原点,提供了设置方法和获取方法,这就没什么可多说的了,最后来看看主函数,该如何使用它们:
主函数中需要引入两个头文件,因为使用到了它们。创建一个矩形变量和一个坐标变量,对它们赋值后,将坐标原点设置给矩形对象,那么此时矩形对象就拥有了坐标原点,之后我们打印出它们的值,编译运行后得到如下结果:
我们修改一下主函数,代码如下:
这里只是对原点进行了二次赋值,那么编译运行后,我们得到如下结果:
为什么会得到这样的结果?我们并没有显式的再次设置矩形的原点,只是对原点对象重新赋值后,矩形的原点也发生了相应的变化。我们来仔细看一下代码,调用setOrigin方法时,point作为参数传递给该方法,这个值是指针对象,指向了XYPoint对象的内存地址。我们使用rect.origin=point将地址赋值给矩形的原点指针上。因为这样赋值的特性,矩形中的原点和point指向的同一内存空间,那么我们修改了point的值,矩形的origin当然也会跟着改变。那么为了避免这个问题,我们修改setOrigin方法的实现,代码如下:
但是我们却得到了如下错误:
这是因为在Rectangle.h中我们使用@class指令来标识XYPoint,而现在需要XYPoint的细节,那么就需要修改头文件,将@class指令改为#import即可。之后修改主函数如下:
编译运行,得到如下结果:
这样就很合理了,原点就属于矩形自己的,称为它的一个属性了,再次修改坐标点不会对已有原点产生影响。但是问题又产生了,修改主函数如下:
如果我们在这里又定义一个对象来获取矩形的原点,然后对其重新赋值,那么我们得到如下结果:
这是因为我们使用origin方法返回时直接返回矩形内的原点引用,那么对这个引用的修改必然导致了上述的结果。出于这种原因,我们要修改origin方法,使其返回一个对象的副本,从而使得对其的修改不影响原有值:
注意这里返回时重新创建了一个对象,对于这种开销是否必要,还要根据实际情况来定。
在继承中,不能删除和减少方法,但可以通过覆盖来实现对方法的更改,还是前面的示例,定义ClassA和ClassB,代码如下:
类A接口中我们只给出变量定义(为了子类可以使用)和初始化方法,其实现代码如下:
这里我们就是实现initVar方法对变量x进行了简单的赋值。那么来看下ClassB的定义:
它继承自ClassA,并且比类A多了打印变量的方法,其实现代码如下:
代码也很简单,就是对x变量的初始化和打印,那这里也是方法覆盖的体现,那来看测试代码:
编译运行,即可得到如下结果:
那么可以看到这里我们创建了类B,并且调用类B的实现代码对变量进行赋值和打印。从而实现了方法覆盖。如果我们将测试代码改写如下:
显然这里类A是没有printVar方法的,那么会得到如下错误:
因此我们需要修改ClassA的代码,加入printVar方法即可。我们分别创建了类A和类B的对象,它们使用各自的initVar方法后就会初始化自己的x变量,之后再使用各自的printVar方法来打印x的值。clsA和clsB按照各自所属的类选择相应的方法,这就是Objective-C中面向对象的基础。
那么如果我们将printVar方法从ClassB中删除,会是怎样的效果?因为ClassB继承自ClassA,如果ClassA中也未定义printVar方法,显然这里会出现错误。但如果ClassA中定义了printVar方法,那么ClassB就会继承这个方法。运行测试代码,也会打印出200这个值。
继承中还有抽象类的概念,如果一个类的创建只是为了更好的创建子类,那么这个类可以叫做抽象类。这样的类中可以定义实例变量和方法,但是不希望任何人从该类来创建实例,比如NSObject。在这里,只要理解抽象类的含义就可以了。
接下文
之前定义了矩形类Rectangle,那么我们如果要在桌面上生成这样一个矩形,就需要定位了。为了简便,我们定义桌面的左下角为直角坐标系(笛卡尔坐标系)的原点,横向向右为X轴正向,竖向向上为Y轴正向。那么我们只要确定了矩形的左下角坐标就可以得到矩形的位置了。此时我们就要引入坐标的概念,那么设计XYPoint类,代码如下:
#import <Foundation/Foundation.h> @interface XYPoint : NSObject @property int x,y; -(void) setX:(int)xVal andY:(int) yVal; @end
XYPoint.h文件定义了坐标类XYPoint的接口信息,这里面我们使用整数作为坐标,暂时不考虑小数坐标点。那么提供一个方法来设置坐标点,其实现代码为:
#import "XYPoint.h" @implementation XYPoint @synthesize x,y; -(void) setX:(int)xVal andY:(int)yVal { x=xVal; y=yVal; } @end
就是给属性x和y进行赋值,没有什么可多说的。因为我们要为矩形设置原点坐标(矩形左下角坐标),那么就需要对矩形类Rectangle进行修改,代码如下:
#import <Foundation/Foundation.h> @class XYPoint; @interface Rectangle : NSObject @property int width,height; -(int) area; -(int) perimeter; -(void) setWidth:(int) w andHeight:(int) h; -(XYPoint *) origin; -(void) setOrigin: (XYPoint *) point; @end
这是类的接口文件,这里面我们使用了@class指令来指定XYPoint类,@class指令可以为我们指定要使用的类,而不用使用import语句,因为这里我们只需要引入XYPoint的定义而已。如果要引用类的实现部分,那么必须使用import语句,@class就不足以提供所需内容了。同时矩形类加入了两个方法,一个是设置原点origin坐标,一个是获取原点坐标,那么矩形类的实现就修改如下:
#import "Rectangle.h" @implementation Rectangle { XYPoint *origin; } @synthesize width, height; -(int) area { return width*height; } -(int) perimeter { return (width+height)*2; } -(void) setWidth:(int)w andHeight:(int)h { width=w; height=h; } -(XYPoint *) origin { return origin; } -(void) setOrigin:(XYPoint *)point { origin=point; } @end
我们定义私有属性origin来表示坐标原点,提供了设置方法和获取方法,这就没什么可多说的了,最后来看看主函数,该如何使用它们:
#import "Rectangle.h" #import "XYPoint.h" int main(int argc, const char * argv[]) { @autoreleasepool { Rectangle *rect=[Rectangle new]; XYPoint *point=[XYPoint new]; [point setX:10 andY:23]; [rect setWidth:10 andHeight:23]; rect.origin=point; NSLog(@"Rectangle: width=%i, height=%i",rect.width,rect.height); NSLog(@"Origin at (%i, %i)",rect.origin.x,rect.origin.y); NSLog(@"Area = %i, Perimeter=%i",rect.area,rect.perimeter); } return 0; }
主函数中需要引入两个头文件,因为使用到了它们。创建一个矩形变量和一个坐标变量,对它们赋值后,将坐标原点设置给矩形对象,那么此时矩形对象就拥有了坐标原点,之后我们打印出它们的值,编译运行后得到如下结果:
我们修改一下主函数,代码如下:
#import "Rectangle.h" #import "XYPoint.h" int main(int argc, const char * argv[]) { @autoreleasepool { Rectangle *rect=[Rectangle new]; XYPoint *point=[XYPoint new]; [point setX:10 andY:23]; [rect setWidth:32 andHeight:36]; rect.origin=point; NSLog(@"Origin at (%i, %i)",rect.origin.x,rect.origin.y); [point setX:23 andY:10]; NSLog(@"Origin at (%i, %i)",rect.origin.x,rect.origin.y); } return 0; }
这里只是对原点进行了二次赋值,那么编译运行后,我们得到如下结果:
为什么会得到这样的结果?我们并没有显式的再次设置矩形的原点,只是对原点对象重新赋值后,矩形的原点也发生了相应的变化。我们来仔细看一下代码,调用setOrigin方法时,point作为参数传递给该方法,这个值是指针对象,指向了XYPoint对象的内存地址。我们使用rect.origin=point将地址赋值给矩形的原点指针上。因为这样赋值的特性,矩形中的原点和point指向的同一内存空间,那么我们修改了point的值,矩形的origin当然也会跟着改变。那么为了避免这个问题,我们修改setOrigin方法的实现,代码如下:
-(void) setOrigin:(XYPoint *) point { if(!origin){ origin=[[XYPoint alloc] init]; } origin.x=point.x; origin.y=point.y; }
但是我们却得到了如下错误:
这是因为在Rectangle.h中我们使用@class指令来标识XYPoint,而现在需要XYPoint的细节,那么就需要修改头文件,将@class指令改为#import即可。之后修改主函数如下:
#import "Rectangle.h" #import "XYPoint.h" int main(int argc, const char * argv[]) { @autoreleasepool { Rectangle *rect=[Rectangle new]; XYPoint *point=[XYPoint new]; [point setX:10 andY:23]; [rect setWidth:32 andHeight:36]; [rect setOrigin:point]; NSLog(@"Origin at (%i, %i)",rect.origin.x,rect.origin.y); [point setX:23 andY:10]; NSLog(@"Origin at (%i, %i)",rect.origin.x,rect.origin.y); } return 0; }
编译运行,得到如下结果:
这样就很合理了,原点就属于矩形自己的,称为它的一个属性了,再次修改坐标点不会对已有原点产生影响。但是问题又产生了,修改主函数如下:
#import "Rectangle.h" #import "XYPoint.h" int main(int argc, const char * argv[]) { @autoreleasepool { Rectangle *rect=[Rectangle new]; XYPoint *point=[XYPoint new]; [point setX:10 andY:23]; [rect setWidth:32 andHeight:36]; [rect setOrigin:point]; NSLog(@"Origin at (%i, %i)",rect.origin.x,rect.origin.y); [point setX:23 andY:10]; NSLog(@"Origin at (%i, %i)",rect.origin.x,rect.origin.y); XYPoint *origin=rect.origin; origin.x=32; origin.y=36; NSLog(@"Origin at (%i, %i)",rect.origin.x,rect.origin.y); } return 0; }
如果我们在这里又定义一个对象来获取矩形的原点,然后对其重新赋值,那么我们得到如下结果:
这是因为我们使用origin方法返回时直接返回矩形内的原点引用,那么对这个引用的修改必然导致了上述的结果。出于这种原因,我们要修改origin方法,使其返回一个对象的副本,从而使得对其的修改不影响原有值:
-(XYPoint *) origin { XYPoint *point=[XYPoint new]; point.x=origin.x; point.y=origin.y; return point; }
注意这里返回时重新创建了一个对象,对于这种开销是否必要,还要根据实际情况来定。
在继承中,不能删除和减少方法,但可以通过覆盖来实现对方法的更改,还是前面的示例,定义ClassA和ClassB,代码如下:
#import <Foundation/Foundation.h> @interface ClassA : NSObject { int x; } -(void) initVar; @end
类A接口中我们只给出变量定义(为了子类可以使用)和初始化方法,其实现代码如下:
#import "ClassA.h" @implementation ClassA -(void) initVar { x=100; } @end
这里我们就是实现initVar方法对变量x进行了简单的赋值。那么来看下ClassB的定义:
#import "ClassA.h" @interface ClassB : ClassA -(void) initVar; -(void) printVar; @end
它继承自ClassA,并且比类A多了打印变量的方法,其实现代码如下:
#import "ClassB.h" @implementation ClassB -(void) initVar { x=200; } -(void) printVar { NSLog(@"x = %i",x); } @end
代码也很简单,就是对x变量的初始化和打印,那这里也是方法覆盖的体现,那来看测试代码:
#import "ClassB.h" int main(int argc, const char * argv[]) { @autoreleasepool { ClassB *clsB=[ClassB new]; [clsB initVar]; [clsB printVar]; } return 0; }
编译运行,即可得到如下结果:
那么可以看到这里我们创建了类B,并且调用类B的实现代码对变量进行赋值和打印。从而实现了方法覆盖。如果我们将测试代码改写如下:
#import "ClassB.h" int main(int argc, const char * argv[]) { @autoreleasepool { ClassA *clsA=[ClassA new]; ClassB *clsB=[ClassB new]; [clsA initVar]; [clsA printVar]; [clsB initVar]; [clsB printVar]; } return 0; }
显然这里类A是没有printVar方法的,那么会得到如下错误:
因此我们需要修改ClassA的代码,加入printVar方法即可。我们分别创建了类A和类B的对象,它们使用各自的initVar方法后就会初始化自己的x变量,之后再使用各自的printVar方法来打印x的值。clsA和clsB按照各自所属的类选择相应的方法,这就是Objective-C中面向对象的基础。
那么如果我们将printVar方法从ClassB中删除,会是怎样的效果?因为ClassB继承自ClassA,如果ClassA中也未定义printVar方法,显然这里会出现错误。但如果ClassA中定义了printVar方法,那么ClassB就会继承这个方法。运行测试代码,也会打印出200这个值。
继承中还有抽象类的概念,如果一个类的创建只是为了更好的创建子类,那么这个类可以叫做抽象类。这样的类中可以定义实例变量和方法,但是不希望任何人从该类来创建实例,比如NSObject。在这里,只要理解抽象类的含义就可以了。
接下文
发表评论
-
Objective-C学习笔记12:高级数据类型一
2013-03-03 21:52 5073接上文 之前介绍过变量和数据类型,那么我们来看 ... -
Objective-C学习笔记11:多态和动态类型
2013-03-03 11:20 8911接上文 多态是一个典型的面向对象概念。Obje ... -
Objective-C学习笔记九:继承一
2013-01-12 20:32 15129接上文 继承是面向对象的一个核心概念。在Obj ... -
Objective-C学习笔记八:类的定义二
2013-01-06 11:00 5374接上文 我们继续来扩展分数类Fraction, ... -
Android学习笔记17:中级视图组件DatePicker和TimePicker
2013-01-05 12:08 16244接上文 HTML5出现之前,我们在Wweb开发 ... -
Objective-C学习笔记七:类的定义一
2013-01-05 10:53 8712接上文 我们还是结合之前分数的示例来说明,只是 ... -
Objective-C学习笔记六:选择结构二
2013-01-03 20:24 5636接上文 之前介绍的都是独立的if选择结构,其实 ... -
Objective-C学习笔记五:选择结构一
2013-01-02 21:37 5752接上文 选择结构,或者称为分支结构,是编程语言 ... -
Android学习笔记16:布局管理器的嵌套
2012-12-31 12:29 9725接上文 布局管理器的嵌套就是将多种布局管理器混 ... -
Objective-C学习笔记四:循环结构
2012-12-31 11:07 8684接上文 ... -
Android学习笔记15:绝对布局管理器AbsoluteLayout
2012-12-29 12:13 11510接上文 有相对布局管理器,对应的,我们还有绝对 ... -
Objective-C学习笔记三:基本数据类型和表达式
2012-12-29 12:06 10193接上文 任何编程语言都会有数据类型,比如在Ja ... -
Objective-C学习笔记二:面向对象概述
2012-12-29 11:49 7194接上文 从字面来理解Objective-C就是 ... -
Android学习笔记14:相对布局管理器RelativeLayout
2012-12-28 13:25 14804接上文 相对 ... -
Objective-C学习笔记一:第一个应用程序
2012-12-27 12:17 14443iOS程序是基于Object ... -
Android学习笔记13:表格布局管理器TableLayout
2012-12-27 11:54 19060接上文 在Web开发中,我们会接触到形形色色的 ... -
Android学习笔记12:框架布局管理器FrameLayout
2012-10-10 10:09 19937接上文 框架布局管理器是Android布局管理 ... -
Android学习笔记11:线性布局管理器LinearLayout
2012-10-02 13:51 15852接上文 和Java GUI部分的概念类似,布局 ... -
Android学习笔记十:基本视图组件:ImageView和ImageButton
2012-09-08 14:05 21666接上文 在Web ... -
Android学习笔记九:基本视图组件:Spinner
2012-09-02 19:58 50211接上文 在Web开 ...
相关推荐
1. **Objective-C是C的超集**:Objective-C在C语言的基础上增加了面向对象的特性,如类、继承、多态等。它允许程序员通过消息传递来调用对象的方法,而不是像C那样直接调用函数。 2. **消息传递**:在Objective-C中...
这篇“Objective-C学习笔记”旨在帮助初学者理解并掌握这种强大的编程工具。 一、Objective-C基础 1. 类与对象:Objective-C中的所有操作都是基于类的,类是对象的模板,而对象是类的实例。理解类和对象的概念是...
Objective-C 是一种面向对象的编程语言,起源于20世纪80年代,由Bard Cox发明,后来在NeXTSTEP操作系统中得到广泛应用。NeXT公司由Steve Jobs创立,并在1996年被苹果公司收购,Objective-C也随之成为苹果操作系统的...
根据给定的学习笔记,我们将从以下几个方面深入探讨Objective-C的基础语法: 1. **基本概念介绍**:包括类、对象、方法等基本概念。 2. **Objective-C核心类型**:如`NSString`、`NSArray`、`NSDictionary`。 3. **...
这份“Objective-C学习资料”包含了内置的学习笔记和各内容源码,是作者在近两个月的学习过程中整理出来的成果,旨在为初学者提供有价值的指导。 首先,让我们深入了解一下Objective-C的基本概念。Objective-C是在...
4. 学习笔记:博主或其他学习者的总结和心得,有助于理解和记忆。 总之,掌握Objective-C是成为Mac和iOS开发者的基石。通过这个入门资源包,你可以系统地学习Objective-C,逐步建立起面向对象编程的思维,并熟悉...
### Objective-C基础教程第二版:OC入门基础教程 #### 一、Objective-C简介与环境搭建 **Objective-C**是一种面向对象的编程语言,它在C语言的基础上增加了面向对象的功能,并且是开发iOS应用的主要语言之一。尽管...
**Object-C 学习笔记** Objective-C(简称Obj-C或Objective C)是苹果公司基于C语言开发的一种面向对象编程语言,主要用于iOS和macOS平台的应用程序开发。它在C语言的基础上添加了Smalltalk风格的消息传递机制,...
Objective-C是在C语言的基础上扩展的,增加了Smalltalk式的面向对象特性,使得它在编写复杂应用程序时具有更高的灵活性和可扩展性。 Objective-C的核心概念主要包括类、对象、消息传递和协议。以下是对这些概念的...
Objective-C是在C语言基础上扩展的,因此它保留了C语言的所有特性,如变量、函数、控制结构等。它的主要扩展是增加了消息传递机制和类的概念,这使得它成为一种面向对象的语言。消息传递是Objective-C的核心,通过向...
Objective-C 是苹果平台下开发 iOS 和 macOS 应用的主要编程语言之一,虽然 Swift 已经成为新宠,但Objective-C 的重要性仍然不可忽视,尤其是因为许多现有的类库和框架仍由 Objective-C 编写。以下是一份关于...
- **类继承**:Objective-C 支持继承,使用冒号 `:` 表示子类继承自哪个父类,如 `Fraction: NSObject` 表示 `Fraction` 类继承自 `NSObject` 类。 - **类变量与成员变量**:类变量(如 `t`)是属于类的,所有实例...
《Objective-C语言教程0220.zip》是一个包含Objective-C编程基础及实例的课程资源包。这个压缩包中,我们能够找到一系列与学习Objective-C语言相关的材料,包括图像和文本文件,旨在帮助初学者理解并掌握这门强大的...
2. **类和继承**:Objective-C 支持类的定义和继承,可以从现有类创建新的类,继承其属性和方法。 3. **协议(Protocols)**:Objective-C 的协议类似于Java或C#的接口,定义了一组必须被遵循的方法,但不强制实现...
Objective-C(简称Obj-C或Objective-C)是苹果公司基于C语言构建的一种面向对象的编程语言,广泛应用于iOS和Mac OS X操作系统。本教程将深入探讨Object-C的基础概念、语法特性以及实际开发中的应用,旨在帮助初学者...
2. **类与对象**:Objective-C基于C语言,增加了类的概念。类是对象的蓝图,而对象是类的实例。定义类时,需要指定其属性(成员变量)和方法(函数)。 3. **类别(Category)**:Objective-C允许为已存在的类添加...
以上内容仅为OC学习笔记合集中的部分知识点概述,深入学习将涵盖更多主题,如Delegation、Design Patterns、网络编程、动画效果、Core Animation等。通过不断实践和探索,你将能够熟练掌握Objective-C,并能构建出...
- 在Objective-C中,`nil`用于表示空指针,与C语言中的`NULL`等价,但在某些上下文中可能有不同的行为。 ### 14. 类别 (Categories) - 类别允许扩展现有类的功能,而不修改原始类的实现。 - 使用`@interface`和`@...