Objective-C中的多态、动态类型和动态绑定

1. 多态能够使来自不同类的对象定义相同名称的方法。

#import <Foundation/Foundation.h>

@interface Complex : NSObject

@property double real, imaginary;
-(void) print;
-(void) setReal:(double) a andImaginary: (double) b;
-(Complex *) add: (Complex *) f;
@end

@implementation Complex

@synthesize real, imaginary;

-(void) print{
    NSLog(@" %g + %gi ", real, imaginary);
}

-(void) setReal:(double)a andImaginary:(double)b{
    real = a;
    imaginary = b;
}

-(Complex *) add:(Complex *)f{
    Complex *result = [[Complex alloc] init];
    result.real = real + f.real;
    result.imaginary = imaginary + f.imaginary;
    return result;
}
@end

@interface Fraction : NSObject

@property int numerator, denominator;
-(void) print;
-(void) setTo: (int) n over: (int) d;
-(double) convertToNum;
-(void) add: (Fraction *) f;
-(void) reduce;
@end

@implementation Fraction
@synthesize numerator, denominator;
-(void) print{
    NSLog(@"%i/%i", numerator, denominator);
}

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

-(double) convertToNum{
    if(denominator != 0)
        return (double) numerator / denominator;
    else return NAN;
}

//添加Fraction到消息接收者
-(void) add:(Fraction *)f{
    // a/b + c/d =  ( (a*d) + (b*c) / (b*d) )
    numerator = numerator * f.denominator + denominator * f.numerator;
    denominator = denominator * f.denominator;
    [self reduce];
}

-(void) reduce{
    int u = numerator;
    int v = denominator;
    int temp;
    
    while (v != 0) {
        temp = u % v;
        u = v;
        v = temp;
    }
    
    numerator /= u;
    denominator /= u;
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Fraction *f1 = [[Fraction alloc] init];
        Fraction *f2 = [[Fraction alloc] init];
        Fraction *fracResult;
        Complex *c1 = [[Complex alloc] init];
        Complex *c2 = [[Complex alloc] init];
        Complex *comResult;
        [f1 setTo:1 over:10];
        [f2 setTo:2 over:15];
        
        [c1 setReal:18.0 andImaginary:2.5];
        [c2 setReal:-5.0 andImaginary:3.2];
        //将两个Complex数相加并显示
        [c1 print];
        NSLog(@" +");
        [c2 print];
        NSLog(@"--------");
        comResult = [c1 add: c2];
        [comResult print];
        NSLog(@"\n");
        
        //将两个分数相加并显示
        [f1 print];
        NSLog(@" +");
        [f2 print];
        NSLog(@"----");
        [f1 add: f2];
        fracResult = f1;
        [fracResult print];
        
    }
    return 0;
}

2. 动态绑定和id类型:id可以用来存储任何类的对象 。注意:在声明id

对象类型时不使用星号。

   如果id类型对象调用其他类型有重名的方法时,系统会先判定对象所属

的类,然后在运行时确定需要动态调用的方法,而不是在编译的时候。

3.id类型与静态类型:

    虽然id数据类型可以用来存储任何类型的对象,但不能滥用这种通用

数据类型。因为:

    将一个变量定义为特定类的对象时,使用的是静态类型。“静态”是指

对存储在变量中对象的类型进行显示声明,这样,存储在这种形态中的

类是预定义的,也就是静态的,这会更方便编译器通过检查来确定应用

于对象的方法是有该类定义的还是由该类继承的。并且,将变量定义为

特定类的对象更方便于读者理解使用该变量的目的。

    关心静态类型是因为它能够更好地在程序编译阶段而不是运行时指出

错误。如果留在运行时你可能都不在现场。

4. 不能对id变量使用点运算符。

5.动态类型的参数和返回类型:

    如果在多个类中实现名称相同的方法,那么每个方法都必须符合各个

参数的类型和返回值类型。如果两个方法之间的不一致仅在于对象类型

的不同,编译器仍可能能够生成正确的代码,因为传递给对象引用的是

内存地址(即指针)。

6. 使用@try处理异常:

    在@try块中加入代码块后,程序正常执行。但是如果块中的某一条语

句抛出异常,执行不会终止,而是立即跳到@catch块,在那里继续执

行。在@catch块内可以处理异常。

猜你喜欢

转载自blog.csdn.net/qq_42347755/article/details/80792205