Trang chủ » Quản lý thư viện bằng Console (Phần 2)
Bài tập tổng hợp

Quản lý thư viện bằng Console (Phần 2)

thu-vien
Cùng nhau khám phá đằng sau thư viện này là gì nhé!

Xin chào mọi người!

Mấy ngày này trời ẩm ướt, phòng tui đột nhiên xuất hiện những sinh vật lạ mà thiên hạ đồn thổi là “kiến ba khoang”. Cảm giác mà khi đặt lưng xuống chiếc giường kí túc xá thân yêu, tự nhiên kề bên là 1 bạn sinh vật nhỏ dễ thương có ba màu đỏ đen như mấy quân bài, đột nhiên bật dậy tỉnh ngủ hẳn :v. Sức khoẻ tác giả vì vậy mà tuột dốc hẳn, vậy nên lâu cập nhật blog mong các bạn thông cảm nhắm mắt bỏ qua cho.

Trở lại vấn đề, ở bài trước mình đã hướng dẫn viết 1 cấu trúc CSDL cho phần mềm quản lý thư viện rồi. Trong đầu các bạn hẳn đã liên tưởng đến cấu trúc cốt lõi của nó, bởi vì việc lập trình bao gồm 90% là thiết kế, suy nghĩ thuật toán, hướng đi, chỉ có 10% còn lại là code thôi. Cho nên mình hi vọng các bạn phải hiểu rõ mình sẽ code những gì trong những bài sắp tới (khuyên nhủ là đừng nên đọc rồi copy/paste mà không hiểu gì nhé 😀 ).

2. Xây dựng class header

Sau khi tạo 1 Project, kèm theo là precompiled header stdafx.h và stdafx.cpp (precompiled header này dùng để tránh việc khi build gặp những thư viện bị trùng lặp sẽ không include thêm vào), bạn tạo 4 class là Books, Account, Customers, Moderators và 1 class riêng để chứa các struct. Code dưới đây nằm toàn bộ trong file header .h, còn file .cpp các bạn cứ để trống:

// Structure.h
#pragma once

struct Date
{
	unsigned short d, m;
	unsigned int y;
};

struct Rent
{
	std::string name;
	unsigned short total;
	Date rentDate;
	Date giveDate;
};

bool operator== (const Date& d1, const Date& d2);
bool operator== (const Rent& r1, const Rent& r2);
// Books.h
#pragma once
class Book
{
private:
	unsigned int ID;
	std::string name;
	unsigned long price;
public:
	// Getter - Setter
	void setID(unsigned int _ID);
	unsigned int getID();

	void setName(std::string _name);
	std::string getName();

	void setPrice(unsigned long _price);
	unsigned long getPrice();
};
// Account.h
#pragma once

using namespace std;

class Account
{
private:
	string username;
	string password;
	string name;
	string identityCard;
public:
	// Getter - Setter
	void setName(string _name);
	string getName();

	void setIdentityCard(string _identityCard);
	string getIdentityCard();

	void setRegisterDate(Date _registerDate);
	Date getRegisterDate();

	void setUsername(string _username);
	string getUsername();

	void setPassword(string _password);
	string getPassword();
};
// Customers.h
#pragma once
class Customer : public Account
{
private:
	unsigned int cID;
	bool isVIP;
	Date registerDate;
	vector<Rent> rentBook;
public:
	// Getter - Setter
	void setID(unsigned int _cID);
	unsigned int getID();

	void setVIP(bool _isVIP);
	bool getVIP();

	void setRegisterDate(Date _registerDate);
	Date getRegisterDate();

	vector<Rent> getRentBook();
};
// Moderator.h
#pragma once
class Moderator : public Account
{
private:
	unsigned int mID;
public:
	// Getter - Setter
	void setID(unsigned int _mID);
	unsigned int getID();
};

Ở từng mục mình có chú thích 1 đoạn là Getter – Setter, ở bên dưới là 1 cặp 2 phương thức get/set và các thuộc tính mình lại để ở chế độ private. Cách làm việc thông dụng của bộ Getter – Setter:

class Test
{
private:
  int myProp;
public:
  // Mình cố tình đặt tên tham số khác đi để dễ thấy
  // Có thể đặt giống cũng không sao, tuy nhiên phải kèm theo con trỏ this
  void setMyProperty(int _myProp) { this->myProp = _myProp; }
  int getMyProperty() { return this->myProp; }
};

Nếu theo lý thuyết thông thường mình học, thì những thuộc tính có access modifier là private thì chỉ có những thành phần bên trong class mới được truy cập. Vậy tại sao mình lại để ở chế độ private? Nếu mình để ở public thì khi sử dụng sẽ tiện lợi hơn là phải sử dụng thông qua phương thức đúng không?

Nghe có vẻ giống như tự đeo cùm vào chân, nhưng thực ra thì đúng thiệt là vậy (Đùa thôi :v). Cặp getter/setter giúp cho việc bạn truy cập vào thuộc tính 1 cách an toàn nhất:

  • Nó giúp bạn ẩn đi tên thuộc tính, bằng cách sử dụng 1 phương thức đại diện. Điều này cũng nguy hiểm tương tự như bạn để lộ cấu trúc field trong CSDL vậy.
  • Dễ dàng nâng cấp, chỉnh sửa. Giả sử bạn có 1 tên thuộc tính là ConMeo, nhưng về sau bạn không muốn nó là ConMeo nữa mà muốn nó là ConCho, thì bạn chỉ việc sửa tên và sửa lại nội dung bên trong bộ getter/setter, thay vì phải lục toàn bộ chương trình và sửa từng chỗ ConMeo thành ConCho.
  • Có thể kiểm tra, bắt lỗi data trong thuộc tính theo ý muốn của bản thân. Giống như 1 thuộc tính email phải chứa nội dung hợp lệ là <tên email>@<tên miền>, chứ không thể chứa nội dung linh tinh.
  • Nếu sau này có 1 class khác kế thừa, thì nó chỉ việc override bộ getter/setter và thiết lập lại.

Trên là những tiện ích của bộ getter/setter mà mình biết được, có thể có vài tính năng khác mà mình chưa biết. Tuy nhiên, ở 1 mức độ thấp thì bộ getter/setter giống như ta đang tự lấy dây trói tay mình vậy, vướng víu khó chịu mà lại càng bực bội (trước đây mình từng nghĩ vậy :v). Tuy nhiên các bạn cũng nên tập làm quen với bộ getter/setter này.

Vì bài viết hiện tại đã quá dài, nên phần file .cpp của từng class mình sẽ cắt ngang và để nó ở phần tiếp theo. Cùng với đó thì mình sẽ giải thích từng tính năng trong mỗi phương thức của từng class, nên mình tạm thời cắt ngang bài viết này.

Cảm ơn các bạn đã chú ý theo dõi, hẹn gặp lại ở Phần 3!

Tags

About the author

Võ Hoài Sơn

Tính tình bất định
Chọc vào là bịnh
Rất yêu lập trình
Luôn code hết mình
Mình hiện đang là sinh viên của trường ĐH Khoa học tự nhiên TPHCM. Bản thân rất thích code, kiêm luôn cả mần thơ nên thường hơi hâm hâm dở dở. Ngoài ra chém gió, chém chuối, chém trái cây các kiểu cũng là sở trường của mình. Rất mong được làm quen với các bạn :D

Add Comment