Feb 18, 2010

Tìm hiểu Objective - C phần 3

tiếp theo phần 2

Kiểu id
id trong ObC gần tương tự như void* trong C. bạn không cần phải biết rõ kiểu của object khi bạn gọi phương thức trong ObC điều này hoàn toàn khác với C++ bơi đơn giản khi gọi phương thức cũng giống như bạn truyền thông điệp trong ObC. Nếu đối tượng nó có phương thức thì sẽ đáp lại thông điệp mà bạn truyền (gọi phương thức) và phương thức đc gọi. Cũng nguy hiểm đây chứ .. :(


Ép kiểu động.
những phương thức dưới đây dùng để kiểm tra kiểu.

- (BOOL) isKindOfClass: classObj >> đối tượng là hậu duệ hoặc thể hiện của classObj
- (BOOL) isMemberOfClass: classObj >> là một thành phần của objClass
- (BOOL) respondsToSelector: selector >> đối tượng có phương thức bởi selector
+ (BOOL) instancesRespondToSelector: selector >> đối tượng đc tạo bởi lớp có đáp ứng selector
- (id) performSelector: selector >> triệu gọi chính sách selector trên đối tượng.


Constructors - hàm khỏi tạo:
Vấn đề là với một lớp thì hàm khởi tạo dùng để sinh đối tượng và cũng là chỗ để tư duy về hàm hủy và cách thức lưu trong bộ nhớ của đối tượng. Về vấn đề hủy đối tượng ta sẽ có một phần riêng và nó hoàn toàn khác biệt với việc viết hàm hủy trong C++ và các ngôn ngữ khác. Tất nhiên không có gì là không thể viết khi bạn đã hiểu rõ và thông thạo ngôn ngữ. Và hẳn nhiên bạn có thể quên hết những luật về khởi tạo đối tượng hàm tạo và hàm hủy của C++ vơi ObC bạn hoàn toàn có thể tự mình chế biến những hàm đó theo ý thích và cũng không có quy luật gì về tên tuổi của hàm, tuy nhiên theo thoi quen truyền thông để giúp style - code chở nên sáng sủa nên dùng bằng các từ như init hoặc tương tự... để định nghĩa hàm khởi tạo


Fraction.h
...
-(Fraction*) initWithNumerator: (int) n denominator: (int) d;
...



Fraction.m
...
-(Fraction*) initWithNumerator: (int) n denominator: (int) d {
self = [super init];

if ( self ) {
[self setNumerator: n andDenominator: d];
}

return self;
}
...



main.m
#import
#import "Fraction.h"

int main( int argc, const char *argv[] ) {
// create a new instance
Fraction *frac = [[Fraction alloc] init];
Fraction *frac2 = [[Fraction alloc] init];
Fraction *frac3 = [[Fraction alloc] initWithNumerator: 3 denominator: 10];

// set the values
[frac setNumerator: 1];
[frac setDenominator: 3];

// combined set
[frac2 setNumerator: 1 andDenominator: 5];

// print it
printf( "The fraction is: " );
[frac print];
printf( "\n" );

printf( "Fraction 2 is: " );
[frac2 print];
printf( "\n" );

printf( "Fraction 3 is: " );
[frac3 print];
printf( "\n" );

// free memory
[frac release];
[frac2 release];
[frac3 release];

return 0;
}

- Từ khóa supper để tham chiếu tới lớp cha.
- Từ khóa self tác dụng tương đương như this trong C++. (chính bản thân đang thể hiện của lớp - object hiện tại)
- Kết thúc hàm khởi tạo (init) sẽ trả về chính đối tượng dc tạo ra thông qua từ khóa self.
- Mặc định trong ObC hàm khỏi tạo là - (id) init;
- Trong ObC hàm khởi tạo chỉ có ý nghĩa về mặt tư duy, nó không đc đối sử đặc biết giống như C++.


Đa hình.
có lẽ với những trình bày ở trên phần nào giúp bạn mường tượng ra dc cơ chế đa hình của ObC. phần này chỉ là viết thêm nhằm củng cố một số những điểm sau đây.
1. Trong ObC không có từ khóa virtual và thực sự là không cần thiết vì nó sẽ không tạo ra những thứ quá phức tạp giống như C++ vì việc phủ quyết hàm trong ObC là phủ quyết trắng chợn không liên quan gì tới sự kế thừa. nếu 2 hàm giống hệt nhau ở 2 lớp quan hệ cha con thì cũng chẳng sao cả. cũng cần nói thêm là ObC là đơn kế thừa.
2. Quá trình tạo mối liên hệ giữa thể hiện của ObC và phương thức sẽ đc gọi là thời điểm run-time. Điểu này hoàn toàn có ý nghĩa nếu bạn gọi một phương thức mà bản thân đối tượng không có cũng không có lỗi gì. Lỗi chỉ xảy ra khi lời gọi đó dc thực hiện. Tuy nhiên ban cũng dc cung cấp những cơ chế để kiểm soát việc này. đây cũng là một đặc tính Run-Time của ObC nếu bạn quan tâm có thể tìm kiếm thông tin từ việc chuyển tiếp thông điệp (forward) tới một đối tượng khác.


Quản ly bộ nhớ.
ObC có 2 lựa chọn cho việc quản lý bộ nhớ. Thông thường bộ nhớ dc quản lý bởi lập trình viên, ObC có trình biên dịch chỉ thị nhứ "release", "retain", "autorelease" là những chỉ thị hỗ chợ lập trình viên mạnh mẽ trong việc quản lý bộ nhớ.
ObC sử dụng một tham chiếu đếm để dò tìm ra những thay đổi trên một đối tượng. Biến đếm này sẽ tăng lên một khi đối tượng dc cấp phát bộ nhớ bằng phương thức alloc, biến đếm này sẽ giảm đi một khi đối tượng dc giải phóng bằng phương thức dealloc. Như vậy nguyên lý cấp phát và duy trì bộ nhớ của đối tượng trong ObC dc sử dụng thông qua phương thức alloc và dealloc.

Mặt khác tiện ích khác từ kiểu dữ liệu nil đã nói ở trên đó việc giải phóng bộ nhơ. Trong ngữ cảnh một đối tượng của bạn là bao gồm nhiều những đối tượng khác. những đối tượng khác đó có thể đã dc giải phóng hoặc chưa. như thế bạn sẽ thực hiện lời gọi dealloc trên tập đối tượng mà bạn có, nếu con thì nó sẽ thực hiện giải phóng trong trường hợp bằng nil cũng ok :D không vấn đề gì (no error) vì nil cũng có thể truyền thông điệp.
hãy xem ví dụ

# AddressCard.h

#import
#import

@interface AddressCard: NSObject {
NSString *first;
NSString *last;
NSString *email;
}

-(AddressCard*) initWithFirst: (NSString*) f
last: (NSString*) l
email: (NSString*) e;
-(NSString*) first;
-(NSString*) last;
-(NSString*) email;
-(void) setFirst: (NSString*) f;
-(void) setLast: (NSString*) l;
-(void) setEmail: (NSString*) e;
-(void) setFirst: (NSString*) f
last: (NSString*) l
email: (NSString*) e;
-(void) setFirst: (NSString*) f last: (NSString*) l;
-(void) print;
@end

# AddressCard.m

#import "AddressCard.h"
#import

@implementation AddressCard
-(AddressCard*) initWithFirst: (NSString*) f
last: (NSString*) l
email: (NSString*) e {
self = [super init];

if ( self ) {
[self setFirst: f last: l email: e];
}

return self;
}

-(NSString*) first {
return first;
}

-(NSString*) last {
return last;
}

-(NSString*) email {
return email;
}

-(void) setFirst: (NSString*) f {
[f retain];
[first release];
first = f;
}

-(void) setLast: (NSString*) l {
[l retain];
[last release];
last = l;
}

-(void) setEmail: (NSString*) e {
[e retain];
[email release];
email = e;
}

-(void) setFirst: (NSString*) f
last: (NSString*) l
email: (NSString*) e {
[self setFirst: f];
[self setLast: l];
[self setEmail: e];
}

-(void) setFirst: (NSString*) f last: (NSString*) l {
[self setFirst: f];
[self setLast: l];
}

-(void) print {
printf( "%s %s <%s>", [first cString],
[last cString],
[email cString] );
}

-(void) dealloc {
[first release];
[last release];
[email release];

[super dealloc];
}
@end

# main.m

#import "AddressCard.h"
#import
#import

int main( int argc, const char *argv[] ) {
NSString *first =[[NSString alloc] initWithCString: "Tom"];
NSString *last = [[NSString alloc] initWithCString: "Jones"];
NSString *email = [[NSString alloc] initWithCString: "tom@jones.com"];
AddressCard *tom = [[AddressCard alloc] initWithFirst: first
last: last
email: email];

// we're done with the strings, so we must dealloc them
[first release];
[last release];
[email release];

// print to show the retain count
printf( "Retain count: %i\n", [[tom first] retainCount] );
[tom print];
printf( "\n" );
// free memory
[tom release];

return 0;
}

# output

Retain count: 1
Tom Jones

Mặt khác ObC cũng cung cấp một cớ chế thông minh thường thường trong việc bạn gọi và sử dụng đối tượng mà không phải quan tâm lo lắng đến việc cấp phát và giải phóng bộ nhớ đó là cơ chế NSAutoreleasePool. Để dùng dc cơ chế này bạn chỉ việc nhớ 2 điều kẹp đoạn code mà bạn muốn kiểm soát vào trong giữa NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init] và [pool release]. Nguyên lý của đồng chí này cũng giống như lời gọi hàm vì thế bạn hoàn toàn có thể sử dụng lồng nhau và sự đóng mở hợp lý (giống như thẻ đóng và mở của XML đó) tự nhiên ObC sẽ đẩy các lời gọi pool sau xuống stack và đặt pool mới trên cùng sau đó nhét các object dc tạo ra trong lòng nó vào cái pool vừa mới tạo nếu song thì giải phóng rồi lại đẩy tiếp thằng pool ở dưới lên cứ thế... kinh chưa :).



Tổng kết:

Đây không phải là một ngôn ngữ compile và là ngôn ngữ run-time. Cho nên trong quá trình code yêu tố này ảnh hưởng rất lớn tới chương trình của bạn. Các đặc điểm như ép kiểu. Đa hình... sẽ rất mềm dẻo.


nội dung bài viết và vi dụ tham khảo tại:


các phần trước.


../..

5 comments:

  1. cảm ơn bài viết của anh nhé!

    ReplyDelete
  2. Bài viết khá hữu ích

    ReplyDelete
  3. Cô đọng, đọc vào hiểu ngay! Tks

    ReplyDelete
  4. thank anh! nhung bai viet nay rat ro rang de hieu!
    Anh co the post them ve lap trinh iphone khong a em dang bat dau tim hieu ve iphone ma trinh do tieng anh van con kem ne mong anh som viet chut tai lieu de em co the tha khao duoc khong a! Cam on anh rat nhieu

    ReplyDelete
  5. Chào Anh Đinh Linh
    Anh có Ebook tiếng việt về objective-c không cho em xin với,Địa chỉ mail của em là: hothangme@gmail.com. Thank Anh

    ReplyDelete

 
Bạn có thể dùng bài viết của tôi tùy ý bạn nhưng vui lòng ghi lại rõ nguồn cung cấp
The world in a click_
Copyright © 2008 linhdkl