標籤:turn int line 繪圖 strong 例子 set 橢圓 http
動態類型和動態綁定,id可以表示任何指標類型,定義id變數不加*
多態性是指在父類中定義的成員變數和方法被子類繼承之後,可以具有不同的資料類型或表現出不同的行為。這使得同一個變數和方法在父類及其各個子類中具有不同的表現形式。我們通過一個例子理解什麼多態,例如:“幾何圖形”類的“繪圖”方法,在它的子類“橢圓形”和“三角形”中也都有“繪圖”的方法,但是“繪圖”方法功能都不同。
Graphics(幾何圖形)類是Ellipse(橢圓形)類和Triangle(三角形)類的父類,Ellipse和Triangle重寫了onDraw方法。
@interface Graphics : NSObject {}-(void)onDraw;@end
#import <Foundation/Foundation.h>#import "Graphics.h"@interface Ellipse : Graphics {}@end#import <Foundation/Foundation.h>#import "Ellipse.h"@implementation Ellipse-(void)onDraw {NSLog(@"繪製橢圓形");}@end
#import <Foundation/Foundation.h>#import "Graphics.h"@interface Triangle: Graphics {}@end#import <Foundation/Foundation.h>#import "Triangle.h"@implementation Triangle-(void)onDraw {NSLog(@“繪製三角形");}@end
#import <Foundation/Foundation.h>#import "Graphics.h"#import "Ellipse.h"#import "Triangle.h"int main (int argc, const char * argv[]) {Graphics *graphics;graphics = [[Ellipse alloc] init];[graphics onDraw];[graphics release];graphics = [[Triangle alloc] init];[graphics onDraw];[graphics release];return 0;}
id 是泛類型 (generic data type), 可以用來存放各種類型的對象, 使用 id 也就是使用“動態類型”。
int main (int argc, const char * argv[]) {id graphics;graphics = [[Ellipse alloc] init];[graphics onDraw];[graphics release];graphics = [[Triangle alloc] init];[graphics onDraw];[graphics release];return 0;}
把Graphics *改成id類型,程式啟動並執行結果沒有任何影響。由於動態類型的關係,id 在執行時,Objective-C 的執行環境會找出該 id 所代表的原來類型,所以根本沒有所謂的轉型。id 並不是自動的轉換成 Ellipse和 Triangle的父類,而是在執行期間, 由執行環境辨認出 id 實際代表的類型為Ellipse還是Triangle。因此在這個例子中id 與Graphics沒有任何關係。
• 定義兩個類:“向量”和“標量”類。
• 向量”即有方向和大小的量,如物理學中的“力”。標量為沒有方向只有大小量,如物理學中的“功”。
@interface Vector : NSObject {double vec1;double vec2;}@property double vec1,vec2;-(void)print;-(void)setVec1:(double)v1 andVec2:(double) v2;-(Vector *)add:(Vector *)v;@end
#import "Vector.h"@implementation Vector@synthesize vec1,vec2;-(void) setVec1:(double) v1 andVec2:(double)v2 {vec1 = v1;vec2 = v2;}-(Vector *)add:(Vector *)v {Vector *result = [[Vector alloc] init];[result setVec1:vec1 + [v vec1] andVec2: vec2 +[v vec2]];return result;}-(void)print {NSLog(@"%g, %g",vec1,vec2);}@end
@interface Scalar : NSObject {double scal;}@property double scal;-(void)print;-(void)setScal:(double)sval;-(Scalar *)add:(Scalar *)s;@end
#import "Scalar.h"@implementation Scalar@synthesize scal;-(void)print {NSLog(@"%g", scal);}-(void)setScal:(double)sval {scal = sval;}-(Scalar *)add:(Scalar *)s {Scalar *result = [[Scalar alloc] init];[result setScal:scal + [s scal]];return result;}@end
#import "Vector.h"#import "Scalar.h"int main (int argc, const char * argv[]) {Scalar *scA =[[Scalar alloc] init];Scalar *scB =[[Scalar alloc] init];Vector *vecA =[[Vector alloc] init];Vector *vecB =[[Vector alloc] init];id scAandB;id vecAandB;[scA setScal: 10.5];[scB setScal: 13.1];[vecA setVec1: 3.2 andVec2: 4.7];[vecB setVec1: 32.2 andVec2: 47.7];... ...[vecA print];NSLog(@" + ");[vecB print];NSLog(@" = ");vecAandB = [vecA add: vecB];[vecAandB print];[scA print];NSLog(@" + ");[scB print];NSLog(@" = ");scAandB = [scA add: scB];[scAandB print];[scA release];[scB release];[scAandB release];[vecA release];[vecB release];[vecAandB release];return 0;}
運行結果:
3.2, 4.7
+
32.2, 47.7
=
35.4, 52.4
10.5
+
13.1
=
23.6
• scAandB和vecAandB對象都是動態類型,都可調用以 "print"和"add"方法。
• 雖然id類型可以任何類型的對象,但是不要濫用,如果能夠確定對象資料類型時候,要使用“靜態類型”,“靜態類型”在編譯階段檢查錯誤,而不是在執行階段。而且“靜態類型”程式可讀性好。
Objective-C語言多態性