zoukankan      html  css  js  c++  java
  • Objective-C语言的面向对象特性

    Objective-C作为一种面向对象的编程语言,具有面向对象的基本特征,即:封装、继承和多态。主要介绍Objective-C中有关面向对象基本概念:类、对象、方法和属性等。

    类是Objective-C中的一种重要的数据类型,是组成Objective-C程序的基本要素。Objective-C的类声明和实现包括两个部分:接口部分和实现部分。

    @interface Song: NSObject {
    … …
    }
    … …
    @end
    @implementation Song
    … …
    @end

    使用关键字@interface(头文件跟C#和JAVA不一样),主要定义了类名、继承的父类、实现的协议、成员变量和方法等信息。下面的代码是Song类的接口部分声明。

    @interface Song : NSObject {
    NSString *title;
    NSString *artist;
    long int duration;
    }
    - (void)start;
    - (void)stop;
    - (void)seek:(long int)time;
    @end

    使用关键字@implementation,主要实现了在接口部分定义的方法等信息。下面的代码是Song类的实现部分声明。

    @implementation Song
    - (void)start {
    //开始播放
    }
    - (void)stop {
    //停止播放
    }
    - (void)seek:(long int)time {
    //跳过时间
    }
    @end

    两个可以放在一个文件,也可放在不同文件。成员变量在构造函数中初始化

    Objective-C中方法定义非常古怪,它遵循了SmallTalk语法风格,它将一个方法名字分成几个部分。

    • 定义了两个参数的方法,第一个参数是anObject,参数类型是id类型,第二个参数是index,参数类型是NSUInteger,这叫做多重参数。它的返回类型是void,方法签名是insertObject:atIndex:。方法类型标识符中都“-”代表方法是实例方法,“+”代表方法是类方法,关于实例方法和类方法我们将在后面内容中讨论。

    如果上面的方法变成C或C+ +形式,则是下面的样子的:

    -(void) insertObjectAtIndex(id anObject, NSUInteger index)

    对于方法的调用通常也不称之为调用,而是称为发出消息,操作符号不是“.”而是“[⋯]”,如下所示:[myObject insertObject: ojb1 atIndex:0];即向myObject对象发出一个消息insertObject:atIndex:0。而在实际使用时候这两种叫法都会用,这不是严格划分。

    从面向对象的封装角度考虑问题,要想访问类中的成员变量,是要通过方法访问的,成员变量前面要有作用域限定符(protected, public, private),这些存取权限修饰符我们将在后面介绍。成员变量的访问,是通过读取方法(getter)和设定方法(setter)。

    @interface Song : NSObject {
    NSString *title;
    NSString *artist;
    long int duration;
    }
    //操作方法
    - (void)start;
    - (void)stop;
    - (void)seek:(long int)time;
    //访问成员变量方法
    - (NSString *)title;
    - (void)setTitle:(NSString *)newTitle;
    - (NSString *)artist;
    - (void)setArtist:(NSString *)newArtist;
    - (long int)duration;
    - (void)setDuration:(long int)newDuration;
    @end
    @implementation Song
    - (void)start {
    //开始播放
    }
    - (void)stop {
    //停止播放
    }
    - (void)seek:(long int)time {
    //跳过时间
    }
    ... ...
    //访问成员变量方法
    - (NSString *)title {
    return title;
    }
    - (void)setTitle:(NSString *)newTitle {
    title = newTitle;
    }
    - (NSString *)artist {
    return artist;
    }
    - (void)setArtist:(NSString *)newArtist {
    artist = newArtist;
    }
    - (long int)duration {
    return duration;
    }
    - (void)setDuration:(long int)newDuration {
    duration = newDuration;
    }
    @end

    采用了封装之后就可以通过存取方法访问属性,例如[mySongtitle]是取得title成员变量内容。如果不考虑封装的问题,单从技术上讲Objective-C,可以直接通过对象访问成员变量的,访问操作符是“->”,例如:mySong->title,也可以取得title成员变量的内容

    在上一小节中对于成员变量的访问,要通过读取方法(getter)和设定方法(setter)。在实现部分也要实现这些读取方法和设定方法,为了简化这些琐碎编码Objective-C2.0提出属性的概念,使用@property关键字在接口部分定义属性,在实现部分使用@synthesize关键字在组装和合成这些属性

    @interface Song : NSObject {
    NSString *title;
    NSString *artist;
    long int duration;
    }
    //操作方法
    - (void)start;
    - (void)stop;
    - (void)seek:(long int)time;
    //访问成员变量方法
    @property(copy,readwrite) NSString *title;
    @property(nonatomic,retain) NSString *artist;
    @property(readonly) long int duration;
    @end

    声明property的语法为:@property (参数) 类型 名字;,这里的“参数”主要分为3大类:基本类型不加内存管理、 内存管理限定,基本数据不需要进行内存管理

    读写属性(readwrite/readonly);

    • 内存管理(assign/retain/copy),这些内存管理的参数,我们将在内存管理小节部分介绍;

    • 原子性atomicity(nonatomic),是关系线程线程安全的,atomicity是原子性的线程安全的,但是会影响性能。如果确定不考虑线程安全问题可以使用nonatomic。

    属性访问用. 如:mySong.title=@"xxxx"; 或者[mySong setTitle:@"xxxx"],[mySong Title],因为属性有限定词后默认有GET SET方法; 成员变量用 ->如: mySong->title=@"xxxx";属性不保存值,通过属性把值传递给成员变量

    @implementation Song
    @synthesize title;
    @synthesize artist;
    @synthesize duration;
    - (void)start {
    //开始播放
    }
    - (void)stop {
    //停止播放
    }
    - (void)seek:(long int)time {
    //跳过时间
    }
    @end

    出于初始化类中的成员变量的需要,可以提供一个方法用于此目的,这个方法就叫构造方法或构造方法(Constructor)。与C++和Java不同,Objective-C命名是

    没有限制的,并且有返回值本身类型指针。

    @interface Song : NSObject {
    NSString *title;
    NSString *artist;
    long int duration;
    }
    //操作方法
    - (void)start;
    - (void)stop;
    - (void)seek:(long int)time;
    //访问成员变量方法
    @property(nonatomic,retain) NSString *title;
    @property(nonatomic,retain) NSString *artist;
    @property(readwrite) long int duration;
    //构造方法
    -(Song*) initWithTitle: (NSString *) newTitle
    andArtist: (NSString *) newArtist
    andDuration:( long int ) newDuration;
    @end

    在Song类的定义中添加了一个方法,它一般用init开头命名,它的返回值很特殊,是返回值本身类型指针。并且有返回值本身类型指针。

    @implementation Song
    @synthesize title;
    @synthesize artist;
    @synthesize duration;
    //构造方法
    -(Song*) initWithTitle: (NSString *) newTitle
    andArtist: (NSString *) newArtist
    andDuration:(long int)newDuration {
    self = [super init];
    if ( self ) {
    self.title = newTitle;
    self.artist = newArtist;
    self.duration = newDuration;
    }
    return self;
    }
    ... ...
    @end

    构造方法的实现代码几乎就是模式代码,基本上都是如下写法:

    self = [super init];
    if ( self ) {
    ……
    }
    return self;

    • 其中使用 [super init] 来调用父类默认构造方法。 这个方法返回的实例对象指派给另一新个关键词:self。self很像 C++ 和 Java 的 this

    • 还有if ( self ) 跟 ( self != nil ) 一样,是为了确定调用父类构造方法成功返回了一个新对象。当初始化变量以后,用返回self 的方式来获得自己的地址。

    父类默认构造方法 -(id) init。技术上来说,Objective-C中的构造方法就是一个 "init" 开头的方法,而不像 C++ 与Java 有特殊的结构。

    • 即便从封装的角度出发,实例成员变量应该定义为

    @private,但作为一种面向对象的语言,Objective-C支持

    @public、@private和@protected作用域限定。如果一个实例变量没有任何的作用域限定的话,那么缺省就是@protected。

    • @public作用域限定的实例变量,可以在任何情况下访问;

    • @private作用域限定的实例变量,只能在这个类里面才可以访问;

    • @protected作用域限定的实例变量,可以在这个类里面和这个类的派生子类里面可以访问这个变量,在类外的访问是不推荐的,但也可以访问。

    @interface Access: NSObject {
    @public
    int publicVar;
    @private
    int privateVar;
    @protected
    int protectedVar;
    }
    @end
    #import "Access.h"
    @implementation Access
    @end
    #import <Foundation/Foundation.h>
    #import "Access.h"
    int main (int argc, const char * argv[]) {
    Access *a = [[Access alloc] init];
    a->publicVar = 5;
    NSLog(@"public var: %i
    ", a->publicVar);
    a->protectedVar = 6;
    NSLog(@"protectedVar var: %i
    ", a->protectedVar);
    //不能编译
    //a->privateVar = 10;
    //NSLog(@"private var: %i
    ", a->privateVar);
    return 0;
    }

    @public、@private和@protected作用域限定只能修饰的实例成员变量,不能修饰类变量,更不能修饰方法类成员默认是protected

    类变量不属于实例个体,类方法用+限定

    #import <Foundation/NSObject.h>
    static int count;
    @interface ClassA: NSObject
    +(int) initCount;
    +(void) initialize;
    @end
    #import "ClassA.h"
    @implementation ClassA
    -(id) init {
    self = [super init];
    count++;
    return self;
    }
    +(int) initCount {
    return count;
    }
    +(void) initialize {
    count = 0;
    }
    @end

    init方法是默认构造方法,在这个构造方法中累计类变量count,在实例方法中可以访问类变量的,但是类方法不能访问实例变量。initCount 方法是一个普通的类方法,用于返回类变量count,initialize方法是非常特殊的类方法,它是在类第一次访问时候被自动调用,因此它一般用来初始化类变量的,类似于C#中的静态构造方法。initialize在所有实例中只执行一次,并且在init之前执行。

    #import <Foundation/Foundation.h>
    #import "ClassA.h"
    int main( int argc, const char *argv[] ) {
    ClassA *c1 = [[ClassA alloc] init];
    ClassA *c2 = [[ClassA alloc] init];
    // print count
    NSLog(@"ClassA count: %i", [ClassA initCount] );
    ClassA *c3 = [[ClassA alloc] init];
    NSLog(@"ClassA count: %i", [ClassA initCount] );
    [c1 release];
    [c2 release];
    [c3 release];
    return 0;
    }

    ClassA count: 2
    ClassA count: 3

    在第一次实例化ClassA时候会调用两个方法: initialize类方法和实例构造方法init,然后再次实例化ClassA时候只是调用实例构造方法init,而没有调用initialize类方法。这样类变量count被一直累加,它隶属类因此c1实例可以访问,c2和c3都可以访问。

  • 相关阅读:
    java 如何读取jar包外的properties文件(转)
    window.showModalDialog()之返回值
    Java web.xml随笔
    如何获取业务表中各位业务员的业务类型A与业务类型B的业务金额
    web.config Web配置文件(*.config)
    Eclipse常用捷键
    css圆角效果
    回车键事件
    WCF学习 之旅
    validation
  • 原文地址:https://www.cnblogs.com/ecollab/p/6123210.html
Copyright © 2011-2022 走看看