2013年8月15日 星期四

Objective-C -- 多型 Polymorphism

polymorphism is a programming language feature that allows values of different data types to be handled using a uniform interface. The concept of parametric polymorphism applies to both data types and functions.
.. from wiki

透過相同的界面進行不同的操作,多型可以應用在資料型別與方法上

書中的解釋更為簡單,Same name, Different Class,不同的類別,相同的名稱,舉個例子,就像是同樣都是叫,鴨子類別中的叫可能是呱呱呱,狗的類別的叫則是汪汪汪。

Animal.h
#import <Foundation/Foundation.h>

@interface Animal : NSObject
{
    NSString *_name;
}
-(void)bray;
@end
Animal.m
#import "Animal.h"

@implementation Animal

-(void)bray
{
    NSLog(@"A......");
}

@end

Duck.h
#import "Animal.h"

@interface Duck : Animal

@end
Duck.m
#import "Duck.h"

@implementation Duck

-(void)bray
{
    NSLog(@"Caw..Caw..Caw.....");
}

@end
Dog.h
#import "Animal.h"

@interface Dog : Animal

@end
Dog.m
#import "Dog.h"

@implementation Dog

-(void)bray
{
    NSLog(@"Wow...Wow..www");
}

@end
main.m
#import <Foundation/Foundation.h>
#import "Animal.h"
#import "Duck.h"
#import "Dog.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        id foo;
        //First subclass
        foo = [[Duck alloc]init];
        [foo bray];
        //Second subclass
        foo = [[Dog alloc]init];
        [foo bray];
        
    }
    return 0;
}

輸出結果:




main.m 當中的 id 是objective-C中泛指所有類別的型別,在其他的語言中,如果沒有這種型別,id 改為 Animal一樣可以,而在Objective-C中兩者都可以使用。
foo變數先指到Duck之後指向Dog,雖然方法名稱都是一樣,但是會根據個別類別中的方法去表現。多型的優點就是,不需要取很多的方法名稱,鴨子叫,狗叫,貓叫...,只要執行時去判斷是哪個類別,在找出相對應的方法即可。

Dynamic typing, dynamic binding

前者是指在執行的過程中,物件動態決定屬於哪個類別,後者則是根據哪種類別去執行方法,用上述的例子來說明

foo = [[Dock] alloc] init];   // dynamic typing
[foo bray];                         // dynamic binding

In runtime決定型別固然很強大,但也有缺點,首先在編譯時,complier無法檢查是否有相對應的方法存在,相反地,如果是用靜態型別 static typing,complier 會確保每個方法對應到正確物件,這可以讓我們在編譯時就發現錯誤而不是在執行的時候,因為你永遠不知道使用者會如何操作,意謂者你不可能測試完所有的可能 ; 再者,使用大量的  id,會讓程式的可讀性降低。

沒有留言: