Tại sao phải sử dụng class & object

Hello mọi người,
-Chuyện là em có học java và đến bài “Class and object”
-Mọi người cho em hỏi là cái “Class and Object” này dùng để làm gì ạ. Trong khi mình có thể
tạo từng hàm và gọi ra giống C. Sao lại phải tạo Object rồi gọi ra… khiến em rất rối đầu.
-Ai giải thích giúp em với
Em cảm ơn.

1 Like

C là ngôn ngữ lập trình thủ tục mà nhỉ ? bạn nên tìm hiểu lại OOP basic

2 Likes

Class là một blueprint, object là các instance. Nhiều instance được tạo ra từ một class. Một class bản vẽ xây được nhiều object căn nhà, một class khuôn bánh làm ra nhiều object cái bánh, một class bản thiết kế sản xất ra được nhiều object chiếc xe, … Và dĩ nhiêu mỗi object là khác nhau : mỗi căn nhà có số nhà khác nhau, mỗi chiếc bánh có mỗi số seri khác nhau, mỗi chiếc xe có mỗi biển số khác nhau.

3 Likes

Class và Object là hai đơn vị cơ bản nhất của OOP rồi. “Nó để làm gì” thì nằm ngay ở chính khái niệm của nó.

Bạn tạo ra 1 class với những thuộc tính (property) và hành vi (method) của nó. Một object được tạo từ 1 class sẽ mang những đặc tính của class đó (với những thuộc tính, hành vi và quan hệ với các đối tượng khác được định nghĩa trong class).
Class thường được xem như bộ khung (prototype) của object. Mình thì hiểu nó như 1 công cụ để nhóm các object ta sẽ tạo ra, ràng buộc các object đó phải có 1 số đặc tính nào đó.


Mọi object tạo thành từ 1 class thì có những đặc tính giống nhau, đó là ý nghĩa của class.

8 Likes

Và vì là hướng đối tượng nên cần có các quan hệ giữa những đối tượng, cần sự tương tác giữa chúng nên mới phải tạo các object.

6 Likes

Để cho cân bằng :smiley: (Why-Not)


open recursion = self.<method> + late binding

5 Likes

tại vì người ta thích gộp dữ liệu và các hàm liên quan tới dữ liệu đó lại chung với nhau. Nhiều hàm chỉ xài cho 1 kiểu dữ liệu nhất định thì gộp chung lại luôn thành cái gọi là class :V :V

trong C ko đặt tên hàm trùng nhau được, ví dụ để so sánh 2 struct với nhau thì phải đặt tên khác nhau: int compareStructA(A *x, A *y), int compareStructB(B *x, B *y) thì thôi gộp struct A và compareStructA lại thành 1 class ví dụ classA luôn cho rồi, khi đó hàm compareStructA chỉ còn có tên là compare thôi :V

trong C khai báo 1 struct thì gọi khai báo đó là struct :V và biến tạo ra từ struct đó cũng gọi là struct :V Với OOP thì khi khai báo/định nghĩa các hàm cho kiểu dữ liệu thì gọi đó là class, còn biến tạo ra từ class đó gọi là object :V

6 Likes

Class là bản vẽ.
Object là sản phẩm chế tạo theo bản vẽ.

6 Likes

Vì như vậy sẽ thì chương trình sẽ dễ phát triển, bảo trì hơn.

4 Likes

Nói trước là mình không cố ý spam link. :sweat_smile:

Khi đang đưa link video về một project mình từng làm để trả lời cho một bạn ở topic khác,
mình nhận thấy video đó cũng dùng làm ví dụ để trả lời cho topic này được.

Trước tiên mời bạn xem video về một game mình từng làm để rèn kỹ thuật lập trình

Như bạn thấy, trong game mình có khá nhiều đối tượng:
chàng trai, cô gái, quái vật, boss,…
Mình sẽ ví dụ 1 chức năng đơn giản nhất là: di chuyển sang trái (hoặc sang phải)

Mỗi đối tượng khi di chuyển sẽ có cách xử lý khác nhau,
ví dụ: chàng trai di chuyển thì mỗi lượt đi được 1 ô, boss thì mỗi lượt nhảy tới 2 ô chẳng hạn,
hơn nữa hình dạng cơ thể khác nhau, nên cũng hiển thị ra khác nhau,
nói cách khác là không sử dụng chung source code được.

Trong khi mình có thể tạo từng hàm và gọi ra giống C

Nếu làm theo cách này, mình sẽ phải tạo ra rất nhiều hàm (như có 1 bạn đã nói ở trên)
qua_trái_chàng_trai(), qua_trái_cô_gái(), qua_trái_boss(),…
chương trình sẽ rất phức tạp và lộn xộn, không có liên kết gì với nhau, khi đọc vào thì bạn sẽ rất khó hiểu nó đang làm cái gì.
VD:

qua_trái_boss()
bắn_boss()
né_chàng_trai()
bắn_boss()
bắt_cô_gái_boss()
bay_đi_boss()

Mình sẽ viết lại theo kiểu hướng đối tượng,
đọc vô dễ hiểu hơn đúng không :sweat_smile:
Ngắn ngắn vầy có thể chưa thấy hiệu quả rõ ràng, nhưng đối với source code hàng trăm đối tượng, hàng ngàn dòng code thì bạn sẽ cảm nhận được rõ ràng.

boss->qua_trái()
boss->bắn()
chàng_trai->né();
boss->bắt_cô_gái();
boss->bay_đi();

8 Likes

Nitpicking: Do tổ chức object kém á. Nếu refactor thành state machine, expose functionality ra API cẩn thận là giải quyết được.

object_t *object_new(object_type_t type, float health, ...);
error_t object_free(object_t *object);

error_t object_move(direction_t direction, float amount, ...);
error_t object_set_state(object_t *object, const state_t *state);
state_t *object_get_state(const object_t *object);

/* state = move, dodge, fly, shoot, bắt cô gái,... */
7 Likes

Kể cả design tốt đến mấy cũng vẫn phải thêm rất nhiều code so với dùng class. Nhất là những phần mà có sử dụng tính đa hình và tính trừu tượng

4 Likes

Đồng ý, viết OO nên pick những ngôn ngữ có đầy đủ constructs hỗ trợ OOP. Mình nitpick riêng ví dụ trên vì không thật sự thuyết phục.

7 Likes

Structured programming: Thay vì dùng goto có thể nhảy lung tung thì dùng if, for, while, return, break, try catch :slight_smile: Cấu trúc ở đây không phải chỉ cái struct, vì struct là type.
Modular programming: Các struct và hàm được gói thành module để “import” vào chương trình.

Khái niệm OOP bắt đầu từ Object passing Messages :slight_smile: hay nói cách khác là đối tượng liên lạc với nhau. Mỗi đối tượng có tính tự quản và để nó tự quản thì cần phải chia responsibility rạch ròi (trừ logging, ACL, auth, rate limiting thì hơi căng :smiley: AOP).

Có hai khái niệm rất khó chịu là SRP và SoC. SRP dùng nhiều thì code toàn là boilerplate thôi.

6 Likes

Mình nghĩ rằng OOP được tạo ra để tổ chức code của một chương trình theo cách mà con người có thể lý luận dễ hơn.

Ở thuở sơ khai của lập trình, người ta viết code chỉ dùng các câu lệnh riêng lẻ và hàm. Đối với một chương trình nhỏ như tìm số lớn nhất của một mảng thì cách lập trình này không có vấn đề gì. Ngược lại, với một chương trình phức tạp hơn như game, phần mềm quản lý bệnh viện,… ta có những sự vật, hiện tượng thực tế cần được mô phỏng lại trong ngôn ngữ máy tính mà cách lập trình chỉ dùng hàm và lệnh khó có thể làm được một cách gần gũi với suy nghĩ con người nhất.

Với OOP, ta có thể sử dụng Class, Object để mô phỏng như sau:

// ví dụ về một sự vật tồn tại trong thế giới thực
class BacSi {
     String maNhanVien;
     String ten;
     Date ngaySinh;

     void tiemVacxinChoBenhNhan(Vacxin vacxin, BenhNhan benhNhan) {
           ...
     }
}

BacSi bacsi1 = heThongBacSi.timBacSiTheoMa("BS1")
BenhNhan benhNhan = heThongBenhNhan.goiBenhNhanTiepTheo();
Vacxin vacxin = heThongVacxin.timVacxinTheoMa("VAC001");

bacsi1.tiemVacxinChoBenhNhan(benhNhan, vacxin)

// ví dụ về một sự vật trừu tượng của máy tính, không tồn tại trong thế giới thực
class List {   
    add(newItem) {
      ...
    }
    remove(itemIndex) {
       ...
    }
}

list.add(1);

Với yêu cầu trên, code OOP sẽ dễ đọc và tự nhiên hơn với cách suy nghĩ của con người: các sự vật hiện tượng (object) đều có phân loại (class), mỗi loại sẽ có những đặc điểm (property) và những hành vi riêng (method).

Tóm lại, phần mềm sinh ra để giải quyết vấn đề thực tế. Để giải quyết được vấn đề thực tế, trước tiên ta cần mô phỏng vấn đề đó vào máy tính (bản đồ, cây cối, con người, dịch vụ, người dùng,…). OOP được sinh ra để mô phỏng sự vật vào máy tính một cách giống suy nghĩ con người nhất. Nhờ vậy code dễ đọc và người viết code dễ dàng lý luận về chương trình.

4 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?