• Objective-C:设值/取值方法、参数设置、self关键字、继承、动态绑定、NSObject基本方法、异常处理


    Objective-C代码的一般组成:

    @interface部分描述类和类的方法(声明)

    exp:

    @interface Fraction: NSObject
    -(void) print;
    -(void) setNumerator: (int)n;
    -(void) setDenominator: (int)d;
    @end

    声明方法时,-表示为实例方法,+表示为类方法;如果有返回值则将返回类型放入-/+后的括号中;如果有接受参数,则方法名以冒号结束,后接内含参数类型的括号和参数名。

    @implementation部分描述数据,并实现接口中声明方法的实际代码(定义)

    exp:

    @implementation Fraction {
        int numerator;
        int denominator;
    }
    -(void) print {
        NSLog (@"%i/%i", numerator, denominator);
    }
    -(void) setNumerator:(int)n {
        numerator = n;
    }
    -(void) setDenominator:(int)d {
        denominator = d;
    }
    @end

    类名与@interface部分名称相同,指定需要存储的数据类型及名称及实现@implementation中的方法。

    @program部分的程序代码实现程序预期目的

    int main(int argc, char *argv[]) {
        @autoreleasepool {
            Fraction *myFraction;
            myFraction = [Fraction alloc]; //分配存储空间
            myFraction = [myFraction init]; //初始化
    //可组合为:Fraction *myFraction = [[Fraction alloc] init];
    //也可用new将alloc和init操作结合:Fraction *myFraction = [Fraction new];
            
            [myFraction setNumerator: 1];
            [myFraction setDenominator: 3];
            
            NSLog(@"The value of my Fraction is: ");
            [myFraction print];
        }
        return 0;
    }

    也可在interface和implementation部分为类声明实例变量。

    按照约定类名一般以大写字母开头,实例变量、对象及方法一般以小写字母开头。

    Id数据类型:一般对象类型,可存储任何类型的对象。

    基础数据类型和限定词表

    double-%g输出,%lf读入

    前缀f、l、u、ll用来明确表示常量是float、long、unsigned和long long类型。

    运算中的类型转换

    整数变量运算中数字的所有小数部分将丢失,如int a=25, b = 2,a/b=12及int i2=-150, i2/100=-1。

    将浮点值赋值给整形变量,所有小数部分将丢失,如float f1=123.125,,int i1=f1,i1=123。

    类型转换运算符(如(float))是一元运算符,不会影响变量的值。(int)将浮点值转换为整数,舍去其中的小数部分。

    赋值运算符op=优先级低于除逗号运算符外的所有运算符,所以a /= b + c相当于a = a / (b + c)。

    去除Xcode时间戳

    #ifdef DEBUG
    #define NSLog(FORMAT, ...) fprintf(stderr,"%s
    ",[[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
    #else
    #define NSLog(...)
    #endif

    优先级:!运算符=一元运算符>二元算术运算符或关系运算符 > &&运算符 > ||运算符>条件与算符>赋值运算符、逗号运算符

    条件运算符从右到左结合。

    Xcode支持条件运算符的ANSI扩展语句:condition ?: expression

    逻辑上等价为condition?condition:expression,对condition求值,若为true则返回值为condition,若为false则返回值为expression。

    Objective-C中内置Boolean变量BOOL类型,预定义值YES和NO。

    设值方法(setter):设置实例变量值的方法;

    取值方法(getter):检索实例变量值的方法;

    设值方法和取值方法通常称为访问器(accessor)方法

    Objective-C 2.0提供自动生成设值和取值方法。首先在接口部分(如:Fraction.h)中添加@property指令:

    #import <Foundation/Foundation.h>
    @interface Fraction : NSObject
    @property int numerator, denominator;
    -(void) print;
    -(double) convertToNum;
    @end

    在实现部分(如Fraction.m)中添加@synthesize指令:

    #import "Fraction.h"
    @implementation Fraction {
        int numerator;
        int denominator;
    }
    @synthesize numerator, denominator;
    -(void) print {
        NSLog(@"%i/%i", numerator, denominator);
    }
    -(double) convertToNum {
        if(denominator != 0)
            return (double)numerator/denominator;
        else
            return NAN;
    }
    @end

    也可不使用@synthesize指令,仅使用@property指令完成,但编译器自动生成的实例变量会以(_)字符作为名称首个字符。

     

    Objective-C支持使用点运算符访问属性。如:

    myFraction.numerator 等价于 [myFraction numerator]

    instance.property = value 等价于 [instance setProperty: value]

    点运算符也支持对自定义的方法使用。

     

    设置具有多个参数的方法,如

    [myFraction setNumerator: 1 andDenominator: 3]或[myFraction setTo:1 over:3]

    在接口文件Fraction.h添加声明:

    -(void) setTo: (int)n over: (int) d;

    在实现文件Fraction.m添加方法定义:

    -(void) setTo:(int)n over:(int)d {
        numerator = n;
        denominator = d;
    }

    在测试程序main.m中声明实例并调用[myFraction setTo:1 over:3] 即可。

    也可不对所有参数都设置参数,如(第二个参数没有命名):

    [aFraction set:100 : 200];

    在接口文件Fraction.h添加声明:

    -(void) set: (int)n : (int) d;

    在实现文件Fraction.m添加方法定义:

    -(void) set:(int)n :(int)d {
        numerator = n;
        denominator = d;
    }

    声明传入参数为该类对象的函数时,应注意参数声明带(*),说明参数是该类对象的一个引用。如,为Fraction类编写add方法:

    在接口文件Fraction.h添加声明:

    -(void) add: (Fraction *)f;

    在实现文件Fraction.m添加方法定义:

    -(void) add:(Fraction *)f {
        numerator = numerator*f.denominator+denominator*f.numerator;
        denominator = denominator*f.denominator;
    }

    在测试程序main.m中声明实例并调用

    [aFraction add:bFraction];

    局部静态变量可的声明通常放置在implementation文件开始处(所有方法声明外部),这样所有实例或类方法都可以访问它们。如:

    #import “Printer.h”
    static int pageCount;
    @implementation Printer
    …
    @end

    self关键字可用于指明对象是当前方法的接收者,是当前对象的引用。如“在add方法中编写[self reduce]使收到add消息的Fraction对象自动约简。

    可创建一个返回值为Fraction的新的add方法。在接口文件Fraction.h添加声明:

    -(Fraction *) add: (Fraction *)f;

    在实现文件Fraction.m添加方法定义:

    -(Fraction *) add:(Fraction *)f {
        Fraction *result = [[Fraction alloc] init];
        result.numerator = numerator*f.denominator+denominator*f.numerator;
        result.denominator = denominator*f.denominator;
        [result reduce];
        return result;
    }

    在测试程序main.m中声明实例并调用

    resultFraction = [aFraction add:bFraction];

    resultFraction最终保存了一个Fraction的对象引用,该对象是在add:方法中创建并通过方法返回的。

     

    继承

    为了使子类能够直接访问到需要使用的实例变量,需要先在接口部分@interface声明。如果实例变量在实现部分声明和合成(synthesize)则是私有的,子类不能直接访问,需要明确定义或合成取值方法((.)或[])才能访问。

    子类继承父类的所有方法和实例变量,类的每个实例拥有自己的实例变量。

    在接口部分,如果编译器需要了解另一个自定义的实例变量的类,可以导入头文件(如:#import “XYPoint.h”),也可以使用指令@class XYPoint;使用@class指令提高了效率,因为编译器不需要引入和处理整个XYPoint.h文件,只需要知道XYPoint是一个类名。

    在实现部分,@class指令是不够的,因为编译器需要更多的消息。

    覆写方法:定义一个同名的新方法,使用和父类相同的名称定义的方法代替或覆写了继承的定义,新方法必须具有相同的返回类型和参数数目。

    抽象(abstract)类/抽象超类(abstract superclass):在该类中定义方法和实例变量,目的在于让使用者更容易创建子类,但不期望任何人从这个类创建实例。

    多态:使不同的类共享相同方法名称的能力。允许开发一组类,这组类中每一个类都能响应相同的方法名,每个类的定义都封装了响应特定方法所需的代码,使其独立于其他的类定义。多态还允许以后添加新的类,这些新类也能够响应相同的方法名。

    将一个变量定义为特定类的对象时使用的是静态类型,静态指对存储在变量中的对象的类型进行显示声明,存储在这种形态中的对象的类是预定义(静态)的。

    动态类型绑定:Objective-C系统总是跟踪对象所属的类,先判定对象所属的类,然后在运行时(不是编译时)确定需要动态调用的方法。

    id数据类型:一种通用的对象类型,可以用来存储任何类的对象。声明为id对象类型的变量可以用来保存不同类型的对象。

    id dataValue;
    Fraction *f1 = [[Fraction alloc] init];
    Complex *c1 = [[Complex alloc] init];
    [f1 setTo:2 over:5];
    [c1 setReal:10.0 andImaginary:2.5];
    dataValue = f1;
    [dataValue print];
    dataValue = c1;
    [dataValue print];

    注意:id对象类型的声明没有使用星号。不能为id变量使用点运算符。

    原因:动态类型绑定。在发送消息给id对象时,先检查id对象中存储的对象所属的类,然后在运行时(不是编译时,存储在id变量中的对象类型在编译时无法确定)确定需要动态调用的方法。

    使用动态类型调用方法时,需要注意如果在多个类中实现名称相同的方法,每个方法必须符合各个参数的类型和返回值类型,编译器才能为消息表达式生成正确的代码。

    NSObject类所支持的一些基本方法

    发送class消息可以根据类名或另一个对象生成一个类对象

    [Square class]; //从名为Square的类中获得类对象
    [mySquare class]; //mySquare是一个实例,查看它所属的类
    if ([obj1 class] == [obj2 class]); //查看存储在变量obj1和obj2中的对象是不是相同的类实例
    [myFraction isMemberOfClass: [Fraction class]]; 测试变量myFract是不是Fraction类的实例

    selector是一个SEL类型的值,可以由一个方法名应用@selector指令生成。如:

    @selector (alloc) //为alloc方法生成一个selector,该方法是从NSObject类继承的
    @selector (setTo:over:) //为setTo:over:方法生成一个selector,该方法是在Fraction类中实现的(注意方法名称中的冒号字符)
    [Fraction instancesRespondToSelector: @selector(setTo:over:)] //测试Fraction类的实例是否相应setTo:over方法(包括继承的方法,并不只测试直接定义在类中的方法)

    performSelector:方法及其变体允许向对象发送消息,这条消息可以使存储在变量中的selector。如:

    SEL action;
    Id graphicObject;
    …
    action = @selector(draw);
    …
    [graphicObject performSelector: action]; /*发送SEL变量action所指定的方法到存储在graphicObject中的任何图形对象*/

     如果需要先确定对象是否可以响应这个动作:

    /*respondsToSelector:判断是否可以将时间的处理委托给你的方法,如果没有实现这个方法,它会按照定义的默认行为自己处理该事件*/
    if ([graphicObject respondsToSelector: action] == YES)
        [graphicObject performSelector: action];
    else
        //错误处理代码

    例:

    int main(int argc, char *argv[]) {
        @autoreleasepool {
            Square *mySquare = [[Square alloc] init];
            
            // isMemberOf:测试类中的直接成员关系
            if([mySquare isMemberOfClass:[Square class]] == YES) //yes
                NSLog(@"mySquare is a member of Square class");
            if([mySquare isMemberOfClass:[Rectangle class]] == YES) //no
                NSLog(@"mySquare is a member of Rectangle class");
            if([mySquare isMemberOfClass:[NSObject class]] == YES) //no
                NSLog(@"mySquare is a member of NSObject class");
            
            // isKindOf:检测继承层次中的关系
            if([mySquare isKindOfClass:[Square class]] == YES) //yes
                NSLog(@"mySqaure is a kind of Square");
            if([mySquare isKindOfClass:[Rectangle class]] == YES) //yes
                NSLog(@"mySquare is a kind of Rectangle");
            if([mySquare isKindOfClass:[NSObject class]] == YES) //yes 检测Square类是否响应alloc类方法
                NSLog(@"mySquare is a kind of NSObject");
            
            // respondsTo:
            if([mySquare respondsToSelector:@selector(setSide:)] == YES) //yes
                NSLog(@"mySquare responds to setSide: method");
            if([mySquare respondsToSelector:@selector(setWidth:andHeight:)] == YES) //yes
                NSLog(@"mySquare responds to setWidth:andHeight: method");
            if([Square respondsToSelector:@selector(alloc)] == YES) //yes
                NSLog(@"Square class responds to alloc method");
            
            // instancesResondTo
            if([Rectangle instancesRespondToSelector:@selector(setSide:)] == YES) //no
                NSLog(@"Instances of Rectangle respond to setSide: method");
            if([Square instancesRespondToSelector:@selector(setSide:)] == YES) //yes
                NSLog(@"Instances of Square respond to setSide: method");
            if([Square isSubclassOfClass:[Rectangle class]] == YES) //yes
                NSLog(@"Square is a subclass of a rectangle");
        }
        return 0;
    }

    使用@try处理异常

    @try {
                [f noSuchMethod];
            }
            @catch(NSException *exception) {
                NSLog(@"Caught %@%@", [exception name], [exception reason]);
            }
            NSLog(@"Execution continues!");
        }

    当@try块抛出异常时,@catch块被执行,包含异常信息的NSException对象作为参数传递给@catch块,name方法检索异常的名称,reason方法给出原因。在@catch块中最后一条语句执行后,程序会立即继续执行之后的语句。

    可使用@throw;指令抛出特定的异常。

    可使用多个@catch块按顺序捕获并处理各种异常。

  • 相关阅读:
    FLEX 几何学
    tcpip协议详解二知识进阶
    打造模块化的Flex应用
    java网络编程知识整理
    ActionScript实现数组快速去重算法
    Adobe Flex迷你教程 — CursorManager使用
    TCP连接中的TIME_WAIT状态二
    TCP连接中的TIME_WAIT状态
    flex 帮助文档制作(HTML)
    Intellij IDEA下flex国际化配置
  • 原文地址:https://www.cnblogs.com/RDaneelOlivaw/p/7660655.html
Copyright © 2020-2023  润新知