Lập trình hướng đối tượng - Sinh viên trình bày điểm giống, khác nhau của C++, C#, Java
Giống nhau:
Hằng là một biểu thức bất kỳ mang một giá trị cố định.
Hằng phải được khởi tạo khi khai báo, và chỉ khởi tạo một lần duy nhất
trong suốt chương trình và không được thay đổi.
Cả 3 ngôn ngữ đều giống nhau về cú pháp khai báo hằng:
< từ khóa > < kiểu dữ liệu > < tên hằng > = < giá trị >;
C++, C# sử dụng từ khóa là const, còn Java sử dụng từ khóa final.
thành hai loại: Kiểu dữ liệu nguyên thủy (primitive) và kiểu dữ liệu tham chiếu (reference). Java chỉ có 3 kiểu dữ liệu tham chiếu: + Mảng (Array): Tập hợp các dữ liệu cùng kiểu + Lớp (Class): Tập hợp các biến và phương thức + Giao diện (Interface): Là một lớp thuần trừu tượng được tạo ra cho phép cài đặt đa thừa kế trong Java. Đối với C++, C# việc truy xất vào vùng nhớ Heap chậm hơn truy xất vào vùng nhớ Stack còn Java có cơ chế cho phép truy cập vào vùng nhớ Heap với tốc độ xấp xỉ bằng tốc độ truy cập vào vùng nhớ Stack. IV. KIỂM TRA KIỂU, ĐỔI KIỂU: 1. Giống nhau: Cả C#, C++, Java đều có cơ chế chuyển kiểu. Việc chuyển kiểu có thể được thực hiện một cách ngầm định (không tường minh) hoặc tường minh. Chuyển kiểu theo cách ngầm định được thực hiện một cách tự động và đảm bảo không mất thông tin, kiểu dữ liệu được chuyển từ cấp thấp hơn sang cấp cao hơn. Còn chuyển kiểu theo cách tường minh, ta phải gọi câu lệnh để thực hiện việc này, và thông tin có thể bị mất đi (khi chuyển kiểu dữ liệu có miền giá trị lớn sang kiểu dữ liệu có miền giá trị nhỏ ) Ví dụ: Trong C#: short x=5; int y=500; y=x; // hop le, chuyen kieu ngam dinh x=y; // khong hop le Muốn gán x bằng y ta phải ép kiểu x=(short) y; // chuyen kieu tuong minh 2. Khác nhau: a. Trong C#: C++, Java chỉ hỗ trợ việc chuyển kiểu giữa các kiểu dữ liệu dựng sẵn, còn C# cho phép khả năng định nghĩa chuyển đổi kiểu tự tạo cho hai đối tượng bất kỳ. Có hai kiểu chuyển đổi là: chuyển đổi tương đối và chuyển đổi tuyệt đối. V. KHÔNG GIAN TÊN: 1. Giống nhau: Không gian tên là ngữ cảnh cho các định danh (identifier), nó cho phép phân biệt các đối tượng có cùng tên (nhưng ở các không gian tên khác nhau). Theo quy tắc, các tên nằm trong một không gian tên không thể nhiều hơn một nghĩa. Nghĩa là, hai hoặc nhiều đối tượng không thể cùng chia sẻ một tên. Mục đích của không gian tên là tránh sự xung đột trong việc sử dụng các thư viện khác nhau từ các nhà cung cấp. Ngoài ra, không gian tên được xem như là tập hợp các lớp đối tượng, và cung cấp duy nhất các định danh cho các kiểu dữ liệu và được đặt trong một cấu trúc phân cấp. Ví dụ: Trong C#: namespace Mylib { using System; public class Test { public void main() { Console .WriteLine(“Well come”); } } } 2. Khác nhau: Trong Java không có khái niệm namespace mà chỉ có khái niêm tương ứng, đó là gói (packet) VI. QUẢN LÝ VÀ CẤP PHÁT VÙNG NHỚ: 1. Gống nhau: Cả ba ngôn ngữ có cùng đặc điểm chung là vùng nhớ dùng để cấp phát bao gồm vùng nhớ Stack và vùng nhớ Heap. Vùng nhớ Stack dành cho các biến (đối tượng) có kiểu dữ liệu giá trị, con trỏ, chúng ta tham chiếu đến các vùng nhớ này thông qua tên biến, việc cấp phát trên Stack khá đơn giản và hoàn toàn giống nhau Vùng nhớ Heap dành cho các biến (đối tượng) có kiểu dữ liệu tham chiếu (đối với C#, Java), hoặc dành cho con trỏ, mảng động (đối với C++), và cấp phát cho các hàm, phương thức khi ta gọi tới nó. 2. Khác nhau: Sự khác nhau thể hiện ở phương thức cấp phát và thu hồi vùng nhớ trên Heap. a. Trong C++: C++ cung cấp cho chúng ta 2 toán tử new và delete để cấp phát và thu hồi vùng nhớ trên Heap, địa chỉ vùng nhớ này sẽ được quản lý thông qua biến con trỏ. Ngoài ra, C++ còn hỗ trợ cho chúng ta hàm hủy, hàm này được gọi tự động khi đối tượng bị hủy, thông thường hàm huỷ mặc định là đủ để dọn dẹp, tuy nhiên trong một số trường hợp thì hàm huỷ mặc định lại không thể đáp ứng được, do vậy người lập trình C++ phải viết ra hàm huỷ riêng để làm việc đó. b. Trong C#: Kiểu tham chiếu như các đối tượng thì được cấp phát trên Heap. Khi một đối tượng được cấp phát trên Heap thì địa chỉ của nó được trả về, và địa chỉ này được gán đến một tham chiếu. Việc cấp phát và thu hồi vùng nhớ được tiến hành một cách tự động thông qua dịch vụ thu nhặt những đối tượng không sử dụng nữa (garbage collector) c. Trong Java: Để quản lý Heap, bộ nhớ được theo dõi thông qua 2 danh sách: + Danh sách các vùng nhớ đã cấp phất + Danh sách các vùng nhớ chưa cấp phát Khi có một yêu cầu về cấp phát vùng nhớ, hệ thống xem xét trong danh sách chưa cấp phát để lấy ra khối bộ nhớ có kích cỡ sát nhất, việc này giúp giảm tối thiểu sự phân mảnh Heap. Java sử dụng 2 Heap riêng biệt cho việc cấp phát vùng nhớ, một Heap chứa các định nghĩa về lớp, các hằng và danh sách các phương pháp, Heap còn lại được chia làm 2 phần được cấp phát theo 2 chiều ngược nhau, một bên chứa đối tượng còn một bên chứa con trỏ đến đối tượng đó. Java hỗ trợ trình dọn rác, nó tự động thu lại vùng nhớ của các đối tượng không sử dụng nữa, thông thường trình dọn rác được kích hoạt khi hệ thống rảnh, nhưng khi có yêu cầu cấp bách thì trình dọn rác có thể được kích hoạt ngay. Trình dọn rác còn có khả năng dọn dẹp các tài nguyên bên ngoài thông qua phương thức finalize. VII. HÀM TRÙNG TÊN: 1. Giống nhau: Cả ba ngôn ngữ đều cho phép chúng ta xây dựng các hàm (hoặc các phương thức trong cùng lớp) trùng tên nhưng có số lượng tham số (không xét đến tham số ngầm định) khác nhau, hoặc kiểu dữ liệu của tham số khác nhau. Khi gọi hàm, trình biên dịch sẽ phân tích số lượng cũng như kiểu dữ liệu các tham số truyền vào để từ đó chọn được hàm cần gọi. Ví dụ: Trong C++: #include int Toan(int a, int b) // Ham 1 { return a/b; } float Toan(float a, float b) // Ham 2 { return a/b; } int Toan(int a, int b, int c) // Ham 3 { return a+b+c; } void main() { int x=5, y=2, z=1; float u=7, v=3; cout << Toan(x,y) << “\n”; // Goi ham 1 cout << Toan(x,y,z) << “\n”; // Goi ham 3 cout << Toan(u,v) << “\n”; // Goi ham 2 } 2. Khác nhau: a. Trong C#: Ngoài việc chồng hàm, C# còn hỗ trợ việc nạp chồng toán tử, khi chúng ta tạo ra toán tử cho một lớp thì chúng ta hoàn toàn có thể nạp chồng toán tử đó. b. Trong Java: Ngoài việc chồng hàm, Java hỗ trợ phương thức ghi đè (overriding), hiện tượng trong lớp cơ sở và lớp dẫn xuất có hai phương thức giống hệt nhau (cả tên lẫn bộ tham số) gọi là phương thức ghi đè (overriding). Bên trong lớp dẫn xuất, nếu có hiện tượng ghi đè thì phương thức bị ghi đè của lớp cơ sở sẽ bị ẩn đi, để có thể gọi phương thức bị ghi đè của lớp cơ sở ta dùng từ khoá super để truy cập đến lớp cha. VIII. NHẬP XUẤT: 1. Giống nhau: Nhập/ xuất là một yêu cầu cơ bản của một chương trình, tất cả các ngôn ngữ lập trình đều cung cấp cho chúng ta các công cụ để thực hiện việc nhập xuất. Có 2 cách nhập xuất cơ bản: + Nhập xuất thông qua các thiết bị nhập xuất chuẩn I/O + Nhập xuất file 2. Khác nhau: a. Trong C++: C++ cung cấp cho chúng ta thư viện stream để thực hiên việc nhập xuất, hai toán tử thường hay sử dụng để thực hiện việc nhập xuất là cin và cout. Ví dụ: #include void main() { int a; cin >> a; cout << a; } b. Trong Java: Java thực hiện việc nhập xuất theo dòng (stream), dòng là những ống (pipelines) để gửi và nhận thông tin. Java cung cấp cho chúng ta lớp java.lang.System định nghĩa các dòng nhập xuất chuẩn, bao gồm: + Lớp System.out: Dòng xuất chuẩn dùng để hiển thị kết quả trên màn hình. + Lớp System.in: Dòng nhập chuẩn thường đến từ bàn phím và được dùng để đọc các ký tự dữ liệu. + Lớp System.err: Đây là dòng lỗi chuẩn. Mặc dù java.lang.System cung cấp khá nhiều lệnh phục vụ nhập xuất nhưng vẫn không đủ mạnh để ứng phó với nhu cầu nhập xuất thục tế, chính vì vậy Java còn hỗ trợ cho chúng ta hai gói java.io và java.awt.print để thực hiện thao tác nhập/xuất. + Lớp java.io cung cấp rất nhiều lớp con như: InputStream, OutputStream, ByteArrayInputStream, ByteArrayOutputStream, File, FileDescrptor, FileInputStream, FileOutputStream, FilterInputStream, FilterOutputStream, BufferedInputStream, BufferedOutputStream, Reader, Writer, CharArrayReader, CharArrayWriter, PrinterWriter và lớp RandomAccessFile. Mỗi lớp đều có các chức năng riêng biệt và rất có ích trong việc nhập/xuất. + Lớp java.awt.print hỗ trợ việc in ấn. Ví dụ: import java.util.Scanner; public satic void main(String[] args) { public class Example { int a ; Scanner scan= new Scanner(System.in); System.out.print("Nhap a: "); a = scan.nextInt(); System.out.print("a = " + a); } } c. Trong C#: C# cũng thực hiện nhập xuất theo luồng, lớp Stream là lớp cung cấp cho chúng ta các công cụ để thực hiện thao tác nhập xuất. Một số lớp thừa kế từ lớp Stream như FileSteam, MemoryStream, và NetworkStream, một số phương thức hay sử dụng của lớp Stream là Read(), Write(), BeginRead(), BeginWrite(), Flush(). Một ưu điểm của C# đó là bất đồng bộ nhập xuất (asynchronous I/O), thông thường chúng ta hay sử dụng kiểu nhập xuất đồng bộ(synchronous I/O), nghĩa là trong chương trình, khi chúng ta thực hiện thao tác nhập/xuất thì các hoạt động khác phải ngừng lại, việc này tiêu tốn khá nhiều thời gian, đặc biệt là khi phải đọc các file có dung lượng khá lớn và được lưu trữ tren bộ nhớ ngoài. C# khắc phục nhược điểm này bằng kĩ thuật bất đồng bộ nhập xuất, nghĩa là chúng ta thực hiện thao tác nhập xuất (vd: đọc file), sau đó quay lại thực hiện các câu lệnh không liên quan đến file đó, như vậy sẽ tiết kiệm được thời gian. Nhận xét: Ta có thể thấy rằng, C++ đã có hỗ trợ cho chúng ta các công cụ để lập trình hướng đối tượng, tuy vậy nó vẫn mang nhiều đặc ddieemrr của lập trình hướng thủ tục, tiếp sau đó đến Java, Java mang nhiều đặc điểm của lập trình hương đối tượng hơn, các đặc điểm như sự đóng gói, tính kế thừa, sự đa hình đều thể hiển rõ hơn, mỗi câu lệnh trong Java đều xuất phát từ class. C# là một ngôn ngữ hương đối tượng, tất cả mã nguồn được viết trong khai báo một lớp, các tính chất của lập trình hương đối tượng đều được thể hiện rõ trong C#.
File đính kèm:
- Lập trình hướng đối tượng - Sinh viên trình bày điểm giống, khác nhau của C++, C#, Java.pdf