Phần 3: “Quan hệ” giữa các đối tượng trong Objective-C | Lập Trình TV

ICTSharing

Bài trước chúng ta đã nắm được những khái niệm cơ bản về lập trình hướng đối tượng (OOP), đã phân biệt được cách thức tổ chức các đối tượng trong chương trình Objective-C (tách riêng tệp interface và tệp lớp khởi tạo dựa trên interface đó). Trong bài này, chúng ta sẽ tìm hiểu sâu hơn về việc khởi tạo các đối tượng và tính thừa kế.

Con trỏ và khởi tạo đối tượng

Giả sử chúng ta muốn làm việc với một chuỗi ký tự, cụ thể là các thao tác nhập giá trị và in giá trị của chuỗi đó lên màn hình. Vậy chúng ta sẽ phải làm thế nào? Đoạn mã dưới đây sẽ minh họa điều trên:

Chương trình trên được tạo trong Xcode bằng cách vào File> New Project> Mac OS X> Application> Command Line> Type: Foundation (khá là đơn giản) và gõ nội dung của chương trình trên vào file main.m (lớp chạy chính của project).
Tiếp theo chúng ta sẽ tìm hiểu cụ thể cấu trúc của một chương trình viết bằng Objective-C. Chương trình Objective-C được xây dựng theo kiểu OOP nên bao gồm nhiều lớp (file có đuôi là .m), trong đó không thể thiếu được một lớp chạy chính đó là main.m (file này mặc định được tạo sẵn trong project mới).
Dòng đầu tiên của file main.m là dòng khai báo sử dụng các thư viện chứa các đối tượng có sẵn (API) trongObjective-C hoặc do ta tạo ra. Cụ thể ở ví dụ trên, chúng ta sẽ báo với compiler biết rằng trong chương trình sẽ sử dụng các API cơ bản của foundation framework (foundation.h)
#import 
Để làm việc với một xâu ký tự chúng ta phải tạo ra một con trỏ đến một đối tượng NSString (tham khảo bài 2) gọi làtestString. Câu lệnh đầu tiên chỉ là câu lệnh khai báo biến con trỏ tham chiếu đến chuỗi ký tự, thực sự thì chuỗi ký tự chưa được khởi tạo và chưa sẵn sàng để chứa các ký tự. Câu lệnh thứ 2, chúng ta mới khởi tạo tạo ra đối tượng cụ thể có thể chứa chuỗi ký tự.
NSString *testString;
testString = [[NSString alloc] init];
Trên đây là cách viết tắt, còn cách viết đầy đủ thì câu lệnh thứ 2 ta sẽ phải tách làm 2 câu lệnh và cụ thể như sau:
NSString *testString;
testString = [NSString alloc];
[testString init];
Cách viết này có thể làm bạn bối rối vì đó là cách viết đầy đủ. Bạn có thể dùng theo cách viết ngắn gọn ở trên bằng cách lồng 2 ngoặc [] trên cùng một dòng lệnh. Tiếp tục sau khi đã khởi tạo thành công đối tượng xâu, chúng ta sẽ gán giá trị xâu cố định “Sample Text” cho nó. Cách thức thể hiện thao tác gán như sau:
testString = @"Sample Text";
Các bạn đã thấy, chúng tôi có thêm ký tự @ trước xâu ký tự là để báo với compiler biết rằng chuỗi văn bản sau @ là một NSString. Như vậy là đối tượng xâu đã có giá trị, vậy làm thế nào ta có thể in giá trị xâu đó ra màn hình? Ở đây ta sẽ không dùng những hàm IO của C mà chúng ta sẽ dùng một đối tượng có sẵn trong foundation framework. Đó là đối tượng NSLog với cú pháp như sau:
NSLog(@"testString: %@", testString);
Ở đây, đối tượng NSLog sẽ in một thông điệp ra màn hình console với cú pháp như trên. Phần trong nháy kép là giá trị xâu cố định và đi theo sau dấu @ và trong nháy kép là vị trí đặt giá trị của biến đối tượng xâu NSString đại diện với ký tự %@. Đó là quy định khi giá trị của một đối tượng xâu NSString ra màn hình console. Kết thúc phần nháy kép trong NSLog sẽ là là phần tiếp theo ngăn cách bởi dấu phẩy (,) chứa danh sách các biến con trỏ tham chiếu đến đối tượng chuỗi NSString, cụ thể mỗi một vị trí %@ sẽ in ra được một giá trị của một con trỏ xâu NSString theo đúng thứ tự. Để gỡ rối và chạy chương trình trong Xcode ta nhấn vào nút Run ở góc trái trên phần cửa sổ project và nhìn kết quả ở cửa sổ output bên dưới màn hình Xcode như hình bên dưới:
Kết quả cuối cùng, chương trình sẽ trả về 0, điều này báo với hệ điều hành rằng mọi thao tác trong chương trình đã kết thúc và không có vấn đề bất thường gì cả.

Thừa kế (Inheritance)

Ở phần trên các bạn đã thấy cách chúng tôi thao tác với NSString. Có phải chúng tôi sử dụng các phương thức init? Đúng NSMutableStringNSArray và trong thực tế, bất cứ lớp NS nào cũng sử dụng phương thức init. Có vẻ ở đây chúng ta lãng phí rất nhiễu mã lệnh để đưa các phương thức init trong mỗi lớp, điều đó có đúng không? Thực sự là không phải vậy, trong OOP có một khải niệm đó là tính thừa kế (Inherinance), nó cung cấp cho ta một khả năng đó là khi có nhiều lớp có tính chất và hành động giống nhau thì ta sẽ tạo ra một lớp chứa các tính chất và hành động chung đó (lớp này gọi là lớp cha), sau đó các lớp con sẽ thừa kế tới lớp cha và có thể dùng lại các tính chất cũng như hành động của lớp cha mà không phải viết lại bất cứ dòng lệnh nào. Và thực tế là ở trong foundation framework, các lớp thư viện đều có chung một nguồn gốc, có nghĩa là tất cả các lớp đều thừa kế tới một lớp gốc, đó là lớp NSObject. Tất nhiên quá trình thừa kế này có thể tiếp tục để các lớp con cháu, chắt sẽ thừa kế lớp con của lớp cha. Tuy nhiên sự thừa kế ở đây là sự thừa kế đơn. Có nghĩa là một lớp con chỉ thừa kế một lớp cha mà thôi. Chúng ta sẽ nhìn vào sơ đồ bên dưới để thấy được sự phân câp quan hệ giữa một số lớp cơ bản trong foundation framework. Chúng tôi xin lưu ý rằng: việc nắm vứng sơ đồ qua hệ các class là hết sức quan trọng trong công việc lập trình của bạn sau này.

Ở sơ đồ trên, các tác giả của Objective-C chỉ cần tạo trong NSObject một phương thức gọi là init và sau đó các lớp con sẽ thừa kế tới lớp NSObject để dùng lại phương thức init và để đảm bảo các đối tượng con sẽ được khởi tạo một cách đúng đắn giống nhau. Tuy nhiên trong quá trình thừa kế, các lớp con có thể ghi đè hay sửa đổi nội dung một số đặc tính hay phương thức của lớp cha. Đó gọi là thừa kế có cải tiến hay còn gọi là ghi đè phương thức (method overiding). Lý do của việc này theo phương pháp lập trình OOP khi các lớp con cùng thừa kế một lớp cha nhưng nó vẫn muốn đảm bảo tính đa dạng hay hay đa hình của các đối tượng con khi tạo ra có thể khác nhau chút xíu từ hình thức đến một số chi tiết hoạt động. Việc này hoàn toàn là hợp lệ và rất hiệu quả bời vì chúng ta hoàn toàn có thể tạo ra một lớp mới dựa trên những lớp đã có sẵn nhưng chúng ta cũng có thể thêm một số gia vị khác ở trên những lớp con đó và tạo nên sự đặc trưng riêng của những lớp do ta tạo nên. Việc này thực chất rất gần gũi với quan hệ giữa các đối tượng trong đời sống thực. Ví dụ bài toán quản lý phương tiện (Vehicle), tất cả các phương tiện sẽ đều có những tính chất chung giống nhau nên ta tạo ra một lớp vehicle đóng vai trò là lớp cha và sau đó ta sẽ tạo ra những lớp con như Car, Bus, Truck… sẽ có cùng chung đặc điểm của lớp vehicle nhưng lại có một số đặc điểm và hoạt động chi tiết khác nhau. Ví dụ sau sẽ minh họa lớp Bus thừa kế tới lớp Vehicle:

Tổng kết

Cho đến thời điềm này, chúng tôi chắc các bạn đã nắm được một số nguyên tắc cơ bản của OOP trong Objective-C. Để có thể kiểm tra những kiến thức mình đã học, xin mời các bạn trả lời một số câu hỏi sau:
  • Sự khác biệt giữa một lớp và một đối tượng là gì?
  • Tại sao chúng ta sử dụng các lớp?
  • Tại sao phải sử dụng tính thừa kế?

Lưu ý:Series 6 bài viết về lập trình Objective-C này được sưu tầm từ nguồn trang:http://az4you.wordpress.com. Loạt bài viết nhằm phục vụ cho các bạn những kiến thức cơ bản ban đầu trước khi bắt tay vào học lập trình ứng dụng cho iOS (iPhone/iPad). ICTSharing xin thay mặt những người yêu lập trình Objective C gửi lời cảm ơn tới các tác giả gốc của các bài viết này! Các bạn cần lưu ý, dù là lập trình bằng bất kỳ ngôn ngữ nào, cho thiết bị nào thì nguyên lý cơ bản của nó cũng không có nhiều sự khác biệt, vì thế nếu bạn đã nắm vững một ngôn ngữ thì các ngôn ngữ còn lại sẽ không quá khó khăn nếu bạn thực sự tập trung. Trong thời gian chờ đợi ICTSharing ra mắt các video về hướng dẫn lập trình trên iOS, các bạn hãy tập trung nắm vững các phần cơ bản của ngôn ngữ Objective-C nhé.

«
Bài sau
Newer Post
»
Bài trước
Older Post

Bình luận

No comments :