BÀI 3: LẬP TRÌNH LỚP VÀ ĐỐI TƯỢNG
2. Cài đặt lập trình lớp - class
2.1. Quy tắc lập trình lớp trong Java. Thành viên dữ liệu và hàm
a) Khai báo và định nghĩa lớp
Một lớp được định nghĩa theo cú pháp sau:
[public] [final] [abstract] class <tên_lớp>
{
// khai báo các thuộc tính của lớp
kiểu_dữ_liệu <tên_biến>;
// khai báo các phương thức của lớp
kiểu_dữ_liệu <tên_hàm(kiểu_dữ_liệu tên_biến_tham_số)>
{ //Các lệnh trong thân phương thức.
} }
Chú ý: Các thành phần trong cặp ngoặc vuông [] là thành phần tùy chọn.Các thành phần trong cặp ngoặc nhọn <> là thành phần bắt buộc người dùng tự đặt tên theo qui tắc đặt tên biến. Một lớp luôn tồn tại cặp ngoặc móc {} để xác định phần bắt đầu và kết thúc của khai báo lớp.
Ví dụ 3.2.1: Định nghĩa lớp hình tròn với các thuộc tính: tọa độ tâm (x,y), bán kính (bk) và phương thức tính diện tích.
public class HINHTRON
{
// khai báo các thuộc tính của lớp
private float bk;
private int x,y;
// khai báo các phương thức của lớp
public float dt() { return bk*bk*3.14;
} }
Một số chú ý:
Mặc định, một lớp chỉ có thể được sử dụng bởi một lớp khác trong cùng một gói với lớp đó, nếu muốn gói khác có thể sử dụng được lớp này thì
ta phải khai báo lớp với từ khóa public.
Nếu có từ khóa abstract, chương trình dịch java biết đây là một lớp trừu tượng, ta không thể tạo ra một thể hiện của lớp này.
Nếu có từ khóa final, chương trình dịch java biết đây là một lớp hằng, không thể kế thừa.
Từ khóa class báo cho chương trình biết ta đang định nghĩa lớp.
Từ khóa extends xác định lớp ta đang định nghĩa kế thừa từ lớp nào.
implements là từ khoá cho java biết lớp này sẽ triển khai giao diện
interface, đây là một dạng tương tự như kế thừa bội của java.
b) Khai báo thuộc tính
Thuộc tính (properties) của lớp được khai báo bên trong lớp như sau:
class <ClassName>
{
// khai báo những thuộc tính của lớp
<Phạm vi truy nhập> <kiểu dữ liệu> tên_biến;
//…
}
Thuộc tính của lớp là một biến có kiểu dữ liệu bất kỳ, nó có thể lại là một biến
có kiểu là chính lớp đó.
Khi khai báo các thành phần của lớp (thuộc tính và phương thức) có thể dùng một trong các từ khóa private, public, protected để giới hạn sự truy nhập đến thành phần đó:
Các thành phần private chỉ có thể được truy nhập từ bên trong thân các phương thức của lớp đó.
Các thành phần protected cũng giống với private nhưng có thể truy nhập
từ bất cứ lớp con nào kế thừa từ nó.
Các thành phần public có thể được truy nhập từ bên trong lẫn bên ngoài lớp.
Nếu một thành phần của lớp khi khai báo mà không sử dụng một trong ba từ khóa private, public hoặc protected thì sự truy nhập là bạn bè, tức là thành phần này
có thể được truy nhập từ bất cứ lớp nào trong cùng gói với lớp đó. Như vậy, các thành phần mặc định sẽ có phạm vi nhìn thấy được rộng hơn các thành phần private, nhưng hẹp hơn các thành phần protected.
Chú ý: Ta phải phân biệt được việc khai báo như thế nào là khai báo thuộc tính,
khai báo như thế nào là khai báo biến thông thường? Câu trả lời là tất cả các khai báo bên trong thân của một lớp và bên ngoài tất cả các phương thức (bao gồm cả hàm tạo) là khai báo thuộc tính, các khai báo ở những nơi khác là khai báo biến.
Có thể minh họa cơ chế phạm vi của các thành viên qua sơ đồ sau:
Hình 3.2.1: Mô hình cơ chế phạm vi các thành viên
Như vậy qua minh họa chúng ta thấy các thành viên private chỉ được sử dụng bên trong lớp, các thành viên protected được sử dụng bên trong và ngoài lớp nhưng chỉ bên trong tệp chương trình, còn public có thể dùng cả bên trong và bên ngoài lớp, ngoài tệp chương trình.
c) Khai báo và định nghĩa phương thức
Cú pháp chung để định nghĩa một hàm:
[<Phạm vi truy nhập>]<Kiểu trả về> <Tên hàm >
([<Danh sách tham biến hình thức>]) [<Mệnh đề throws>]
{
//Các lệnh trong thân phương thức
} Trong đó:
<Kiểu trả về> có thể là kiểu nguyên thủy, kiểu lớp hoặc không có giá trị trả lại (kiểu void).
Lớp
A Tệp chương trình (*.java)
priv
ate
prot
ected
publ
ic
<Danh sách tham biến hình thức> bao gồm dãy các tham biến (kiểu và tên) phân cách với nhau bởi dấu phẩy.
<Phạm vi truy nhập> chỉ tính chất của phương thức, có thể có các từ khóa thể hiện như sau: public, protected, private, mặc định (không chỉ rõ tính chất nào), static, abstract, final, native, synchoronized.
<Mệnh đề throws>: là một đối tượng đặc biệt được tạo ra khi chương trình gặp lỗi. Java sẽ trả lại cho chương trình ngoại lệ này theo từ khóa throws. Các ngoại lệ, nếu có, được phân cách nhau bởi dấu phẩy.
Các tính chất public, protected, private, static, final và mặc định (không chỉ rõ phạm vi) của hàm tương tự như đối với thuộc tính chứa dữ liệu của lớp. Còn các tính chất abstract, synchronized và native được sử dụng với các ý nghĩa như sau:
Các hàm abstract
Hàm thành phần khai báo trừu tượng (abstract) có dạng:
abstract <Kiểu trả về> <Tên hàm>([<Danh sách tham biến>])[<Mệnh đề
throws>];
Hàm abstract là hàm prototype, chỉ khai báo phần định danh hàm mà không
định nghĩa nội dung thực hiện, do vậy nó là hàm không đầy đủ. Hàm abstract
thường chỉ tổ chức cho các lớp abstract và nó phải được cài đặt nội dung thực hiện
ở trong các lớp con cháu của lớp chứa hàm đó.
Lưu ý:
- Hàm final không thể khai báo abstract và ngược lại.
- Các hàm trong interface đều là các hàm abstract.
Các hàm synchronized
Java hỗ trợ chương trình thực hiện đa luồng (multi threads). Có thể có nhiều luồng muốn thực hiện đồng thời trên một đối tượng nào đó. Có những loại thiết bị,
ví dụ như máy in, kênh truyền chẳng hạn, đòi hỏi phải có cơ chế để chỉ một luồng được thực hiện, nghĩa là phải thực hiện đồng bộ. Tại mỗi thời điểm, chỉ một luồng (tiến trình) được khai báo đồng bộ synchronized được thực hiện trên đối tượng chỉ định.
Các hàm native
Hàm khai báo native được gọi là hàm ngoại. Nội dung thực hiện của hàm native không được định nghĩa trong Java mà định nghĩa ở những ngôn ngữ lập trình
khác như C/C++. Những hàm native chỉ cần khai báo prototype như là các thành
phần của lớp.
JNI (Java Native Interface) là một loại API (Abstract Programming Interface) cho phép các hàm của Java gọi tới hàm ngoại được cài đặt trong C.
Chú ý:
o Nếu trong lớp có ít nhất một phương thức trừu tượng thì lớp đó phải là lớp trừu tượng.
o Không có thuộc tính trừu tượng.
o Ta không thể tạo đối tượng của lớp trừu tượng.
o Khác với ngôn ngữ C++, các phương thức của lớp trong java yêu cầu người dùng bắt buộc phải khai báo giá trị trả về cho phương thức, nếu phương thức không trả về dữ liệu thì dùng từ khóa void. (Trong ngôn ngữ C++ thì mặc
định phương thức sẽ trả về kiểu int nếu ta không chỉ rõ giá trị trả về)
Thông thường một thành phần của lớp chỉ truy xuất trong sự liên kết với một đối tượng thuộc lớp của nó. Tuy nhiên, có thể tạo ra một thành phần mà có thể dùng một độc lập một mình, không cần tham chiếu đến một đối tượng cụ thể, có thể được truy xuất trước khi bất kỳ đối tượng nào của lớp đó được tạo ra, bằng cách đặt trước khai báo của nó từ khoá static. Cách truy xuất hàm lớp :
<Tên lớp>.<Tên phương thức>(Danh sách tham số);
Các hàm toán học của lớp Math trong Package Java.Lang là hàm lớp nên khi gọi không cần phải khởi tạo đối tượng Ví dụ : double a = Math.sqrt(9);