Tải bản đầy đủ (.docx) (34 trang)

[Bài Học Số 1] Cơ Bản Objective Cx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (221.64 KB, 34 trang )

1. Một vài dòng về lịch sự ra đời và sự phát triển.
Lịch sử ra đời
The wiky thì Bard Cox và Tom Love (không biết có thằng cha này không nhưng thấy wiki nó
nói thì mình cũng đưa ra đây chắc lão Tom Love này cũng có chút ít công sức) thuộc
Stepstone là cha đẻ của Objective - C. Ngôn ngữ này đc giới thiệu năm 1981 và chúng ta
cũng nhớ rằng thập niên 80s của thế kỷ trước là sự lên ngôi của khái niệm lập trình OOP
cũng là giai đoạn cực thịnh của sự ra đời các ngôn ngữ OOP trên nên C. Tiếp tục hoàn thiện
trong vài năm đến 1986 Cox chính thức ấn hành chuẩn của Objective - C trong các cuốn
sách Object-Oriented Programming, An Evolutionary Approach.
Sự kế tiếp của Steve Jobs
Cái tên này đã chở nên qua nổi tiếng từ cuộc đời ông cho đến sự nghiệp lẫy lừng và cả việc
ông làm điên đảo cộng đồng IT thế giới cho đến chính bạn (chẳng phải bạn cũng đang diên
đảo vì IPhone đây !_! )
Khi bi out khỏi Apple, năm 1988 Steve Jobs đã mua lại bản quyên của Obejctive - C từ
Stepstone để viết cho ứng dụng phần cứng của mình. vọi là NeXTstep hay còn gọi là
OpenStep công ty lúc này của Jobs là NeXT.
Cho đến 1996 khi Apple mua lại NeXT thì họ tiếp tục sử dụng công nghệ OpenStep để phát
triên hệ điều hành Mac của họ và xây dựng một loạt công cụ XCode, Interface Builder .. và
các Cocoa API ra đời...
Đến giờ thì đã hiểu là tại sao lại là Objective - C chứ không phải bất cứ ngôn ngữ nào khác
để build các App trên nền Apples.
2. Tìm hiểu ngôn ngữ Ob-c
Đặc điểm cơ bản.
- Là ngôn ngữ hướng đối tượng
- Mở rộng từ C
- Nhẹ nhàng (không VM - không quá thực tạp với friend virtuals với template với ....)
- Mềm dẻo (mở rộng từ C nên bạn có thể dùng C thuần cấu trúc ngoài ra đây là ngôn ngữ
run-time)
- Reflection (có hỗ chợ)
- nil thay thế cho NULL trong C, bởi vì bạn có thể gửi thông điệp cho nil, nhưng không thể
làm như vậy với NULL.


- BOOL có 2 giá trị là YES và NO chứ không phải là true và false nữa.
- Khái niệm methods và message đc sử dụng mang ý nghĩa như nhau đối với ObC theo đó
message có những thuộc tính đặc biệt. Mọto message có thể chuyền động từ obj tới một obj
khác. Việc gọi thông điệp trên một obj không có nghĩa là obj đó sẽ thực hiện message nó có
thể chuyển tiếp tới một obj khác chưa biết trước tóm lại có khả năng đáp trả thông điệp
không trực tiệp thì gián tiếp.
Khi làm việc với Objective C bạn cần chú ý là bởi vì nó dc base trên nền của C cho nên việc
bạn sử dụng cú pháp C chộn lẫn với cú pháp chính thống của Objective C là hoàn toàn chấp
nhận, tuy nhìn có vẻ hơi củ chuối.
Phương thưc.
Cách khai báo phương thức trong Objective - C
Không tham số :
PHP Code:
<(kiểu trả về)> Tên_phương_thức
ví dụ
PHP Code:
-(void) print;
Có tham số:
PHP Code:
<(kiểu trả về)> Tên_phương_thức :<(kiểu)> Tên_Biến :<(kiểu)> Tên_Biến;
ví dụ:
PHP Code:
-(void) setDenominator: (int) d;
Lời gọi phương thức:
Mã:
không trả về: [<đối tượng> ];
[<đối tượng> :<(kiểu)> ];
[<đối tượng> :<(kiểu)> :<(kiểu)> ];
Trả về kết quả: = [<đối tượng> ];
= [<đối tượng> :<(kiểu)> :<(kiểu)> ];

Lớp và đối tượng.
Ob-C sử dụng khái niệm Interface và Implementation để phân biêt file Header và file Source
của C (*.h và *.c) một lớp trong ObC định nghĩa là trên một giao diện (.h) còn phần thực thi
trên file .m các bạn chú ý là m vì nó khác với C và C++.
@interface:
Code:
PHP Code:
#import @interface Fraction: NSObject {
int numerator;
@private
int denominator;
}
-(void) print;
-(void) setNumerator: (int) n;
-(void) setDenominator: (int) d;
-(int) numerator;
-(int) denominator;
@end
và đây là phần thực thi.
@implementation
Code:
PHP Code:
#import "Fraction.h"
@implementation Fraction
-(void) print {
printf( "%i/%i", numerator, denominator );
}
-(void) setNumerator: (int) n {
numerator = n;
}

-(void) setDenominator: (int) d {
denominator = d;
}
-(int) denominator {
return denominator;
}
-(int) numerator {
return numerator;
}
@end
- Sử dụng #import để thay thế cho #include (đây là cơ chế thông minh hơn #include của C/C++ bạn chỉ
phải thêm 1 lần thôi )
- ObC chỉ cho phép đơn kế thừa. Mặc định tất cả các lớp sẽ kế thừa từ NSObject.
- Cặp @.... và @end là cặp giới hạn phạm vi một lớp.
- Các thuộc tính dc khái báo trong cặp { ..... } và khai báo phương thức ở bên ngoài.
- Nếu phương thức bắt đâu bằng "+" có nghĩa nó là thuộc phạm vi lớp (static), còn nếu "-" thì nó ở
phạm vi object.
- Các phạm vi truy xuất public,protected và private giống như C++ mặc định là protected.
- Các truy nhập phần tử cũng sử dụng toán tử "." đối với object và "->" nếu là con trỏ.
- không có các tầm vực truy xuất đối với phương thức (tức là trong ObC các phương thức có cùng một
tầm vực là public)
Exception và handler.
Ngôn ngữ cũng hỗ chợ các cấu trúc try - catch - throw - finally giống như ngôn C++ @try -
@catch - @throw - @finally cách thức sử dụng cũng hoàn toàn tương tự.
Categories
Là đặc điểm nếu bạn muốn mở rộng lớp bằng cách thêm mới vào lớp một phương thức. Khi
bạn làm việc quen với OOP thì bạn sẽ thấy đây là một trong những thuộc tính vô cùng hữu
ích của Objective C, kể cả ngay khi bạn không có mã nguồn của lớp nhưng bạn vẫn hoàn
toàn có thể thêm phương thức cho lớp như thường thông qua thuộc tính này. Đặc điểm này
làm giảm đi đáng kể sự kế thừa phức tạp trong C++ khi việc kế thừa chỉ để phục vụ cho

việc thêm mới một phương thức. Mặt khăc việc chia mã nguồn trên nhiều files cũng giúp ích
đáng kể trong việc phát triên.
Code:
PHP Code:
#import "Fraction.h"
@interface Fraction (Math)
-(Fraction*) add: (Fraction*) f;
-(Fraction*) mul: (Fraction*) f;
-(Fraction*) div: (Fraction*) f;
-(Fraction*) sub: (Fraction*) f;
@end
File thực thi.
Code:
PHP Code:
#import "FractionMath.h"
@implementation Fraction (Math)
-(Fraction*) add: (Fraction*) f {
return [[Fraction alloc] initWithNumerator: numerator * [f denominator] +
denominator * [f numerator]
denominator: denominator * [f denominator]];
}
-(Fraction*) mul: (Fraction*) f {
return [[Fraction alloc] initWithNumerator: numerator * [f numerator]
denominator: denominator * [f denominator]];
}
-(Fraction*) div: (Fraction*) f {
return [[Fraction alloc] initWithNumerator: numerator * [f denominator]
denominator: denominator * [f numerator]];
}
-(Fraction*) sub: (Fraction*) f {

return [[Fraction alloc] initWithNumerator: numerator * [f denominator] -
denominator * [f numerator]
denominator: denominator * [f denominator]];
}
@end
- Tên của category phải là duy nhất
- Có thể thêm bao nhiêu lần mở rộng lơp từ category là không giới hạn nhưng với tên là duy nhất.
- Thông thể bổ xung biến thành phần bằng category.
- Có thể sử dụng category để tạo ra các phương thức private. Nếu cần.
MyClass.h
Code:
PHP Code:
#import
@interface MyClass: NSObject
-(void) publicMethod;
@end
MyClass.m
Code:
PHP Code:
#import "MyClass.h"
#import
@implementation MyClass
-(void) publicMethod {
printf( "public method\n" );
}
@end
PHP Code:
// private methods
@interface MyClass (Private)
-(void) privateMethod;

@end
@implementation MyClass (Private)
-(void) privateMethod {
printf( "private method\n" );
}
@end
main.m
Code:
PHP Code:
#import "MyClass.h"
int main( int argc, const char *argv[] ) {
MyClass *obj = [[MyClass alloc] init];
// this compiles
[obj publicMethod];
// this throws errors when compiling
//[obj privateMethod];
// free memory
[obj release];
return 0;
}
cái này thật thú vị phải không, thực ra đây là một hệ quả trực tiếp từ đăc tính run-time của
Objective C.
Protocals: Giao diện.
Đây hoàn toàn tương đồng với khái miện lớp ảo trong C++ hoặc gọi là giao diện trong C#
và Java. Bản thân @protocals không có sự thực thi. Nếu lớp nào cam kết thực thi nó thì
trong phần thực thi sẽ implement các phương thức mà protocals khai báo.
Code:
PHP Code:
@protocol Printing
-(void) print;

@end
Fraction.h
Code:
#import
#import "Printing.h"
@interface Fraction: NSObject {
int numerator;
int denominator;
}
-(Fraction*) initWithNumerator: (int) n denominator: (int) d;
-(void) setNumerator: (int) d;
-(void) setDenominator: (int) d;
-(void) setNumerator: (int) n andDenominator: (int) d;
-(int) numerator;
-(int) denominator;
@end
Fraction.m
Code:
PHP Code:
#import "Fraction.h"
#import
@implementation Fraction
-(Fraction*) initWithNumerator: (int) n denominator: (int) d {
self = [super init];
if ( self ) {
[self setNumerator: n andDenominator: d];
}
return self;
}
-(void) print {

printf( "%i/%i", numerator, denominator );
}
-(void) setNumerator: (int) n {
numerator = n;
}
-(void) setDenominator: (int) d {
denominator = d;
}
-(void) setNumerator: (int) n andDenominator: (int) d {
numerator = n;
denominator = d;
}
-(int) denominator {
return denominator;
}
-(int) numerator {
return numerator;
}
-(Fraction*) copyWithZone: (NSZone*) zone {
return [[Fraction allocWithZone: zone] initWithNumerator: numerator
denominator: denominator];
}
@end
Complex.h
Code:
PHP Code:
#import
#import "Printing.h"
@interface Complex: NSObject {
double real;

double imaginary;
}
-(Complex*) initWithReal: (double) r andImaginary: (double) i;
-(void) setReal: (double) r;
-(void) setImaginary: (double) i;
-(void) setReal: (double) r andImaginary: (double) i;
-(double) real;
-(double) imaginary;
@end
Complex.m
Code:
PHP Code:
#import "Complex.h"
#import
@implementation Complex
-(Complex*) initWithReal: (double) r andImaginary: (double) i {
self = [super init];
if ( self ) {
[self setReal: r andImaginary: i];
}
return self;
}
-(void) setReal: (double) r {
real = r;
}
-(void) setImaginary: (double) i {
imaginary = i;
}
-(void) setReal: (double) r andImaginary: (double) i {
real = r;

imaginary = i;
}
-(double) real {
return real;
}
-(double) imaginary {
return imaginary;
}
-(void) print {
printf( "%_f + %_fi", real, imaginary );
}
@end
main.m
Code:
PHP Code:
#import
#import "Fraction.h"
#import "Complex.h"
int main( int argc, const char *argv[] ) {
// create a new instance
Fraction *frac = [[Fraction alloc] initWithNumerator: 3 denominator: 10];
Complex *comp = [[Complex alloc] initWithReal: 5 andImaginary: 15];
id printable;
id copyPrintable;
// print it
printable = frac;
printf( "The fraction is: " );
[printable print];
printf( "\n" );
// print complex

printable = comp;
printf( "The complex number is: " );
[printable print];
printf( "\n" );
// this compiles because Fraction comforms to both Printing and NSCopyable
copyPrintable = frac;
// this doesn't compile because Complex only conforms to Printing
//copyPrintable = comp;
// test conformance
// true
if ( [frac conformsToProtocol: @protocol( NSCopying )] == YES ) {
printf( "Fraction conforms to NSCopying\n" );
}
// false
if ( [comp conformsToProtocol: @protocol( NSCopying )] == YES ) {
printf( "Complex conforms to NSCopying\n" );
}
// free memory
[frac release];
[comp release];
return 0;
}
Properties
Thuộc tính gần như bất cứ một ngôn ngữ mới hiện đại nào cũng hỗ chợ khái niệm này, đây
là một khái niệm bảo toàn tính đóng gói của tư tưởng OOP.
Đối vơi ngôn ngữ ObC có mốt số những hỗ chợ đặc biệt hơn một chút bạn khai báo sử dụng
bằng @properties cũng giống như những ngôn ngữ khác khi bạn sử dụng thuộc tính với ObC
bạn sẽ có 2 lựa chọn là @synthesize và @dynamic, với lựa chọn là @synthesize thì mặc
nhiên trình biên dịch sẽ giúp bạn sinh ra các phương thức set và get trên thuộc tính. nhưng
nếu bạn lựa chọn là @dynamic thì mọi việc bạn phải tự làm lấy.

hãy xem code
Code:
PHP Code:
#import
@interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
- (NSString*) caption;
- (NSString*) photographer;
- (void) setCaption: (NSString*)input;
- (void) setPhotographer: (NSString*)input;
@end

Code:
PHP Code:
#import
@interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
@property (retain) NSString* caption;
@property (retain) NSString* photographer;
@end
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ứ ..

DE XEM LINK VA HINH ANH BAN CAN CO NHIEU HON 10 BAI VIET. NHUNG HIEN TAI BAN
CHI CO 0 BAI VIET.
Ép kiểu động.
những phương thức dưới đây dùng để kiểm tra kiểu.
Trích dẫn:
- (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
Code:
PHP Code:
...
-(Fraction*) initWithNumerator: (int) n denominator: (int) d;
...
Fraction.m
Code:
PHP Code:

...
-(Fraction*) initWithNumerator: (int) n denominator: (int) d {
self = [super init];
if ( self ) {
[self setNumerator: n andDenominator: d];
}
return self;
}
...
main.m
Code:
PHP Code:
#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
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
Code:
PHP Code:
#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
Code:
PHP Code:
#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] );
}

×