Ở bài này chúng ta cùng tìm hiểu về Ngôn ngữ lập trình Objective C, ngôn ngữ được sử dụng để lập trình iOS.
Ở phần này mình giả sử các bạn được có “môi trường làm việc” MAC OS, đã cài đặt IDE Xcode.
Chúng ta sẽ chưa bắt tay vào lập trình nên các ứng dụng iOS, mà ở bài viết này chúng ta sẽ tìm hiểu về Objective C, các kiểu dữ liệu, cú pháp câu lệnh, hướng đối tượng,…
Ở phần này mình giả sử các bạn được có “môi trường làm việc” MAC OS, đã cài đặt IDE Xcode.
Chúng ta sẽ chưa bắt tay vào lập trình nên các ứng dụng iOS, mà ở bài viết này chúng ta sẽ tìm hiểu về Objective C, các kiểu dữ liệu, cú pháp câu lệnh, hướng đối tượng,…
Video Bài 2:
1) Khởi tạo dự án ví dụ
Mở Xcode và tạo một dự án để bắt đầu nắm các kiến thức cơ bản
về Objective C.
Chúng ta tạm thời chấp nhận các phần hiện có, chưa cần thiết
phải tìm hiểu ở bước này, ở phần này chúng ta tập trung tìm hiểu Objective C.
Click chọn ViewController, chúng ta sẽ tìm hiểu Objective từ đây
2) Cơ bản Objective C
Ngôn ngữ lập trình Objective-C là một ngôn ngữ lập trình hướng
đối tượng được xây dựng chủ yếu dựa trên nền tảng ANSI C, và ngoài ra nó còn được
mở rộng từ Smalltalk, một trong những ngôn ngữ lập trình hướng đối tượng đầu
tiên. Objective-C được thiết kế với mục đích đưa vào C các tính năng hướng đối
tượng một các đơn giản và dễ hiểu nhất.
Objective-C là ngôn ngữ chính được Apple chọn để viết các ứng
dụng cho hệ điều hành MAC, iPod và iPhone.
a) Kiểu dữ liệu cơ bản
Cũng tương tự như C, Objective C có các kiểu dữ liệu cơ bản
như int, short, float, char, BOOL…
int i = 0;
short s = 0;
float f = 1.0f;
char *c = "c";
BOOL b = YES;
b) Kiểu đối tượng
Lập trình iOS chúng ta sẽ cần sử dụng đến Cocoa Touch
framework (chúng ta chỉ cần biết vậy đã, nói chung nó nằm trong nền tảng mà
Apple cung cấp cho chúng ta có thể lập trình được trên iOS), mọi đối tượng
trong nền tảng này đều kế thừa từ một lớp cơ sở là NSObject.
NSObject *obj;
Từ lớp này chúng ta có nhiều lớp con khác nhau: NSString,
NSArray,…
c) Định kiểu động
Objective C cung cấp một định kiểu dữ liệu động
id anObject;
Với id, chúng ta sẽ không biết anObject là đối tượng gì
(NSArray hay NSString…) mà chỉ đơn giản biết nó là một đối tượng. Điều này khá
hữu ích cho chúng ta trong một số trường hợp mà chúng ta không thực sự quan tâm
đến loại đối tượng mà ta đang làm việc là loại gì, chỉ cần biết đó là đối tượng
để tham chiếu, so sánh…
d) Cú pháp câu lệnh
Các câu lệnh điều kiện, lặp trong Objective C cũng tương tự
như của C
if (<#condition#>) {
<#statements#>
} else if
(<#expression#>) {
<#statements#>
} else {
<#statements#>
}
switch (<#expression#>) {
case <#constant#>:
<#statements#>
break;
default:
break;
}
for (<#initialization#>;
<#condition#>; <#increment#>) {
<#statements#>
}
while (<#condition#>) {
<#statements#>
}
do {
<#statements#>
} while
(<#condition#>);
e) Hàm và lời gọi hàm
Định nghĩa hàm và cú pháp gọi một hàm trong Objective-C có
khác biệt khá nhiều với các ngôn ngữ lập trình mà ta thường biết như Java, C,
C++…
Hàm thì vẫn có kiểu trả về, tên hàm và tham số, tuy nhiên cú
pháp của Objective-C khá ngộ.
- (void)demoMethod:(int)param1 with:(NSString *)param2
and:(float)param3
{
}
Đây là cú pháp của một hàm trong Objective-C, các tham số
thường không đặt trong cặp dấu () như các ngôn ngữ khác mà chúng được tách biệt
ra bởi ký tự trắng và dấu :
Như hàm trên có 3 tham số, ta thấy từ with, and được đặt ở
đây nhằm mục đích mô tả thêm cho tham số 2 và 3.
Với hàm trên, chúng ta có thể làm gọn lại như sau
- (void)demoMethod:(int)param1 :(NSString *)param2 :(float)param3
{
}
Tức là bỏ đi with, and và như vậy chỉ còn lại ký tự trắng và
dấu :
Tuy cả 2 cách đều đúng, nhưng theo mình thì chúng ta nên sử
dụng cách đầu, nó làm cho hàm của chúng ta tường minh hơn.
3) Hướng đối tượng trong Objective C
Phần này chúng ta sẽ cùng lướt qua các khái niệm chính về hướng
đối tượng trong Objective-C. Ở mục này mình mặc định là các bạn đã biết, quen
thuộc với hướng đối tượng và ở đây chúng ta chỉ xem là hướng đối trong
Objective-C sẽ như thế nào.
a) Lớp
Từ Xcode chúng ta New một lớp mới như sau
Như đã nói ở trên, lớp đối tượng cơ bản nhất trong
Objective-C là NSObject, chúng ta sẽ chọn cho lớp của mình MyClass kế thừa từ lớp
này
Tương tự như ngôn ngữ C/C++, Objective-C sẽ tạo ra 2 file
cho lớp MyClass:
-
file header (MyClass.h) dùng để khai báo các
thông tin cho lớp
-
file m (MyClass.m) là nơi khai báo các đoạn mã
thực thi của lớp
-
Trong 2 file MyClass.h, MyClass.m chúng ta thấy
//MyClass.h
#import <Foundation/Foundation.h>
@interface MyClass : NSObject
@end
//MyClass.m
#import "MyClass.h"
@implementation MyClass
@end
Vậy cú pháp để khai báo một lớp đó là từ khóa @interface
(các bạn không nên nhầm lẫn với khái niệm interface trong hướng đối tượng, vì
đơn giản đây chỉ là từ khóa do Apple qui định, còn khái niệm interface “truyền
thống” sẽ được tìm hiểu ở mục Protocol)
Tương tự như C/C++, kí hiệu : để qui định lớp MyClass của
chúng ta kế thừa từ NSObject, và 1 điều chú ý là Objective-C không hỗ trợ đa kế
thừa.
b) Phương thức/Hàm tạo
Trong Objective-C không có khái niệm phương thức tạo cho một
lớp. Tất cả các đối tượng của một lớp phải được cấp phát thông qua phương thức
alloc và init.
MyClass *myObject = [[MyClass alloc] init];
Trong đó phương thức alloc là cấp phát vùng nhớ, còn phương
thức init như là một phương thức tạo mặc định trong Objective-C, được định
nghĩa trong lớp NSObject.
-(id)init;
Và như vậy, trong MyClass.m chúng ta có thể override lại hàm
init này để khởi tạo các giá trị ban đầu cho lớp của mình, chúng ta sẽ tìm hiểu
ở các mục tiếp theo.,
c) Con trỏ this
Trong hướng đối tượng chúng ta luôn quen thuộc đến khái niệm
con trỏ this, và Objective-C cũng không ngoại lệ. Trong Objective-C, con trỏ
this được biết đến thông qua từ khóa self.
d) Thuộc tính lớp
#import <Foundation/Foundation.h>
@interface MyClass : NSObject
{
@private
int att1;
NSString *str1;
@protected
int att2;
@public
NSString *str2;
int att3;
}
@end
Cách khai báo thuộc tính tương tự C/C++, các chỉ thị truy xuất
cho phép giới hạn truy xuất đến thuộc tính, và mặc định khi không có chỉ thị
này thì sẽ là @protected
Với thuộc tính public, chúng ta có thể truy xuất thông qua đối
tượng của lớp như sau
MyClass *myObject =
[[MyClass alloc] init];
NSLog(@"%@ %d", myObject->str2,
myObject->att3);
Cú pháp tương tự C/C++
Thường thì khi lập trình iOS, mình ít khi sử dụng các thuộc
tính public dạng này, vì nó có một số vấn đề liên quan đến quản lý bộ nhớ mà
mình sẽ đề cập đến sau. Đa số mình dùng protected, tức là không xài các chỉ thị
(private, protected, public) cho tiện J, còn việc truy xuất
thuộc tính “public” bên ngoài thông qua đối tượng thì mình thường sử dụng
Property hơn (khái niệm này sẽ được thảo luận ở mục dưới)
e) Khái niệm Property
Khái niệm Property thực ra tương tự như khái niệm
setter/getter trong các ngôn ngữ khác như java, C#...
//MyClass.h
@interface MyClass : NSObject
{
int myAtt;
NSString *myStr;
}
@property (nonatomic, assign) int att;
@property (nonatomic, strong) NSString *str;
@end
//MyClass.m
#import "MyClass.h"
@implementation MyClass
@synthesize att = myAtt;
@synthesize str = myStr;
@end
Ở file .h, trong phần khai báo lớp, chúng ta có 2 thuộc tính
myAtt và myStr, và mình đã khai báo 2 bộ setter/getter cho chúng thông qua 2 chỉ
thị @property
@property (nonatomic, assign) int att;
@property (nonatomic, strong) NSString *str;
Chúng ta khoan hãy quan tâm đến các chỉ thị nonatomic,
assign, strong, câu hỏi đặt ra là, làm thế nào để có thể mapping được property
att với thuộc tính myAtt, str với myStr để chúng ta có thể quản lý được chúng.
Vấn đề đó ở trong file .m
@synthesize att = myAtt;
@synthesize str = myStr;
Với chỉ thị @synthesize, chúng ta thực hiện mapping property
với thuộc tính trong lớp mà chúng ta cần sử dụng.
Khi đó chúng ta có thể truy xuất các thuộc tính này thông
qua các property
MyClass *myObject =
[[MyClass alloc] init];
myObject.att = 1;
myObject.str = @"Hello
Kungfu";
Ở đây mình đã cố ý đặt tên thuộc tính là myAtt và property
là att để các bạn khỏi bị nhầm lẫn, thực ra mình hoàn toàn có thể đặt tên thuộc
tính là att và khi đó
@synthesize att = att;
Và trong bản thân của lớp, khi mình muốn sử dụng thuộc tính
(biến) att, mình sẽ dùng trực tiếp
att = 1;
Trong trường hợp mình muốn sử dụng property thay vì gọi trực
tiếp biến att, mình sẽ gọi thông qua con trỏ self
self.att = 2;
Trong các phiên bản mới của Xcode, Apple cũng đã linh động
hơn cho chúng ta trong việc khai báo các property này. Ở file .h, mình hoàn
toàn có thể định nghĩa property nhưng không cần phải định nghĩa thuộc tính (biến)
@interface MyClass : NSObject
{
}
@property (nonatomic, assign) int att;
@property (nonatomic, strong) NSString *str;
@end
Và trong file .m mình không còn sử dụng chỉ thị @synthesize
@implementation MyClass
- (id)init {
}
@end
Tuy nhiên trình biên dịch lúc này sẽ tự động ngầm hiểu cho
chúng ta là đã có khai báo 2 thuộc tính
int _att;
NSString *_str;
Các bạn để ý 2 dấu ‘_’ ở trước tên biến, Apple mặc định ngầm
rằng biến “cục bộ” sẽ có định dạng như vậy, và trình biên dịch cũng mặc định
luôn
@synthesize att = _att;
@synthesize str = _str;
Mặc dù chúng ta không hề khai báo, và chúng ta hoàn toàn có
thể truy xuất như trên trong lớp
_att = 1;
self.att = 2;
Lưu ý, trường hợp tự nhận biết này chỉ đúng khi chúng ta chỉ
có khai báo chỉ thị @property, ngoài ra không khai báo thêm gì khác.
Bây giờ chúng ta qua lại với cú pháp chỉ thị @property.
-
phần 1 (nonatomic/atomic): tham số này các bạn
nên chấp nhận nó, khi chúng ta quen thuộc với Objective-C sẽ tìm hiểu thêm
-
phần 2 (assign/retain/strong/copy/readonly): các
tham số này sẽ quy định việc thực thi các bộ setter/getter của chúng ta
o
assign: tạm hiểu là gán ngay, thường dùng cho
các thuộc tính kiểu vô hướng hoặc các liên kết yếu
o
retain/strong: sử dụng khi thuộc tính nắm giữ chủ động vùng nhớ set
o
copy: đúng với ý nghĩa của nó, copy vùng nhớ khi
set
o
readonly: chỉ được đọc (get), không ghi (set)
Phần này chúng ta sẽ tìm hiểu lại một lần nữa ở bài viết quản
lý bộ nhớ trong Objective-C.
f) Phương thức của lớp
Phương thức, cú pháp thì như chúng ta đã làm quen ở trên. Mục
này chúng ta sẽ tìm hiểu cách khai báo phương thức cho lớp.
//MyClass.h
@interface MyClass : NSObject
{
}
@property (nonatomic, assign) int att;
@property (nonatomic, strong) NSString *str;
- (void)publicMethod:(int)param;
+ (int)staticMethod:(int)param;
@end
//MyClass.m
@implementation MyClass
- (void)publicMethod:(int)param;
{
NSLog(@"%d", param);
}
+ (int)staticMethod:(int)param
{
return param + 2;
}
@end
Trong file .h chúng ta sẽ tiền định nghĩa phương thức, với
phần tên, tham số mà không có phần thực thi, nó tương tự cách của C/C++.
Dấu ‘-’ cho biết đây là phương thức public của lớp, có thể
truy xuất thông qua đối tượng.
[myObject publicMethod:1];
Dấu ‘+’ cho biết đây là phương thức static của lớp, có thể
truy xuất thông qua tên lớp
[MyClass staticMethod:2];
Trong Objective-C không có định nghĩa phương thức private rõ
ràng, thường thì chú ta sẽ định nghĩa phương thức này với phần thực thi và
không có phần tiền định nghĩa trong file .h
g) Protocol
Protocol nó cũng tương tự ý nghĩa một interface trong Java,
nó cung cấp cho các lớp thực thi nó một giao tiếp với các phương thức được định
nghĩa sẵn, và giao tiếp này sẽ được sử dụng trong các trường hợp cụ thể mà
chúng ta sẽ tìm hiểu sau. Trước tiên chúng ta sẽ tìm hiểu khai báo một protocol
sẽ như thế nào
@protocol MyProtocol
@optional
- (void)optionalMethod;
@required
- (void)requiredMethod;
@end
Sử dụng từ khóa @protocol để định nghĩa, có 2 chỉ thị
@optional và @required với mục đích rõ ràng như ý nghĩa của nó:
-
Optional: các phương thức đằng sau chỉ thị này
thì các lớp thực thi có thể không cần phải triển khai mã nguồn thực sự
-
Required: các phương thức đằng sau chỉ thị này
thì các lớp thực thi phải triển khai mã nguồn thực sự, nếu không sẽ bị báo lỗi
Và lớp MyClass của chúng ta sẽ thực thi protocol này như thế
nào
@interface MyClass : NSObject <MyProtocol>
- (void)publicMethod:(int)param;
+ (int)staticMethod:(int)param;
@end
#import "MyClass.h"
@implementation MyClass
- (void)optionalMethod
{
}
- (void)requiredMethod
{
}
@end
Như vậy, qua bài này, chúng ta đã làm quen và biết rõ hơn một
chút về Objective-C, ở bài tiếp theo chúng ta sẽ tìm hiểu thêm 1 phần khá quan
trọng, đó là Quản lý bộ nhớ trong Objective-C.
No comments:
Post a Comment