Class cho người mới bắt đầu

vbano1

SMod
Thành viên BQT
Mọi người đã sử dụng Class Module bao giờ chưa?
Nếu như có thể sử dụng Class Module, thì chúng ta có thể lập trình hướng đối tượng với VBA.
Code trở nên chất lượng hơn, tính an toàn của code được nâng cao hơn, tính tái sử dụng code cũng được nâng cao hơn rất nhiều.
Tuy nhiên nhiều người nghĩ sử dụng class module rất khó, nên ngại tìm hiểu. Các bài viết trên các diễn đàn ở VN còn khá tản mạn. Ngay cả trên THVBA, mặc dù hiện tại có tới 2 topic rồi. Nhưng mình vẫn muốn lập thêm một topic nữa. Cố gắng trình bày dễ hiểu nhất có thể.

1. Class Module là gì?
Nó cũng giống như Module bình thường, là một nơi để các bạn có thể viết code vào đó.

2. Cách tạo Class Module:
Bạn click chuột phải vô Project => Insert => Class Module
Bạn cần đăng nhập để thấy đính kèm

Một class mới được tạo ra.
Bạn cần đăng nhập để thấy đính kèm

Bạn vào View => Properties Window .
Bạn cần đăng nhập để thấy đính kèm


Bạn hãy đổi tên class thành: clsPerson
Bạn cần đăng nhập để thấy đính kèm

Hãy dán đoạn code dưới đây vào trong class module:
[B]clsPerson[/B]:
'Bien cau truc
Public Enum PrSex
    prSexMale = 0
    prSexFemale = 1
End Enum

Public Name As String 'Ten
Public Age As Long    'Tuoi
Public Sex As PrSex   'Gioi tinh
Public Address As String 'Dia chi
Theo thiết kế trên thì một người sẽ có 4 thuộc tính: Tên, Tuổi, Giới tính, Địa chỉ.

Bạn không thể làm bất cứ điều gì nếu chỉ có định nghĩa một lớp.
Tác dụng của nó chỉ có thể được phát huy thông qua một Module thông thường.

Hãy tạo module thông thường và viết code như sau:
Module1:
Sub CreateInstance()
    Dim myPerson(1 To 3) As clsPerson
    Dim i As Long
    Dim mySex As String
    For i = LBound(myPerson) To UBound(myPerson)
        Set myPerson(i) = New clsPerson
    Next
    With myPerson(1)
        .Name = "NhanSu"
        .Age = 30
        .Sex = prSexMale
        .Address = "VinhPhuc"
    End With
    With myPerson(2)
        .Name = "Tuhocvba"
        .Age = 32
        .Sex = prSexMale
        .Address = "Tokyo"
    End With
    With myPerson(3)
        .Name = "giaiphapvba"
        .Age = 26
        .Sex = prSexFemale
        .Address = "Osaka"
    End With

    For i = LBound(myPerson) To UBound(myPerson)
        With myPerson(i)
            If .Sex = prSexMale Then
                mySex = "Nam"
            Else
                mySex = "Nu"
            End If
            Debug.Print .Name, .Age & " Tuoi", mySex, .Address
        End With
    Next
End Sub
Hãy thử thực thi code trên và quan sát ở cửa sổ Immediate :
Bạn cần đăng nhập để thấy đính kèm

Bằng cách này, mỗi cá thể có thể có các thuộc tính riêng của nó.
Ta cũng có thể lặp lại và xử lý tất cả các đối tượng cùng một lúc trong một vòng lặp For Each trong mô-đun tiêu chuẩn.

Tuy nhiên vẫn chưa có phương thức hay thuộc tính nào mà chỉ có biến public (biến thành viên).
Nó trông chưa giống một đối tượng.
Trên thực tế, bạn chỉ cần làm như trên, ta đã có các kiểu do người dùng tự định nghĩa.

3. Đóng gói
Trên thực tế, việc sử dụng các biến public, như trong đoạn mã đã giới thiệu ở trên, không được khuyến khích trong lập trình hướng đối tượng.
Điều này là do rất khó để đảm bảo tính bảo mật của dữ liệu vì có thể dễ dàng nhìn thấy hoặc ghi lại dữ liệu.
Để đảm bảo an toàn cho dữ liệu, tất cả các biến cấp mô-đun trong dữ liệu được khai báo trong phạm vi riêng tư (Private) và quá trình xử lý như tham chiếu và thiết lập được thực hiện thông qua các thủ tục.

Bây giờ hãy thay thế code trong Class bằng đoạn code sau:
clsPerson:
'Bien cau truc
Public Enum PrSex
    prSexMale = 0
    prSexFemale = 1
End Enum

Private myName As String
Private myAge As Long
Private mySex As PrSex
Private myAddress As String

'Lay ten
Public Property Get Name() As String
    Name = myName
End Property

'Thiet dinh ten
Public Property Let Name(myNewName As String)
    'Ten da duoc thiet dinh roi thi khong cho thiet dinh lai
    If Len(myName) > 0 Then Exit Property
    myName = myNewName
End Property

'Lay tuoi
Public Property Get Age() As Long
    Age = myAge
End Property

'thiet dinh tuoi
Public Property Let Age(ByVal myNewAge As Long)
    'Neu tuoi vuot qua 150 thi khong cho thiet dinh
    If myNewAge < 0 Or myNewAge > 150 Then Exit Property
    myAge = myNewAge
End Property

'Lay gioi tinh
Public Property Get Sex() As PrSex
    Sex = mySex
End Property

'Thiet dinh gioi tinh
Public Property Let Sex(ByVal myNewSex As PrSex)
    'Gioi tinh ngoai nam hay nu thi khong cho thiet dinh
    If myNewSex <> prSexMale And myNewSex <> prSexFemale Then Exit Property
    mySex = myNewSex
End Property

'Lay dia chi
Public Property Get Address() As String
    Address = myAddress
End Property

'Thiet dinh dia chi
Public Property Let Address(myNewAddress As String)
    myAddress = myNewAddress
End Property
Lớp trên là [tài liệu thiết kế đối tượng con người], tức là lớp.
Bốn thuộc tính "Tên", "Tuổi", "Giới tính" và "Địa chỉ" được giữ lại trong các biến "Name", "Age", "Sex" và "Address", tương ứng.
Vì lớp là một tài liệu thiết kế, bạn có thể tạo và sử dụng bất kỳ số lượng cá thể (thực thể) nào.

Bằng cách đóng gói, tôi chỉ thêm một chức năng kiểm tra tại thời điểm thiết lập dữ liệu, nhưng bạn có cảm thấy phiền phức vì khối lượng code tăng lên không?
Trên thực tế, bằng cách làm này, khối lượng của toàn bộ chương trình có thể được giảm bớt.
Xét trường hợp không đóng gói, khi tạo một chương trình để người ta sử dụng, việc xử lý đối với các hoạt động không thường xuyên được thực hiện.
Trong trường hợp của mã trên, các biện pháp chống lại các hoạt động bất thường(check-kiểm tra) được bao gồm dưới dạng thuộc tính.

Lớp ban đầu chúng ta xây dựng không làm điều đó, vì vậy bạn sẽ cần thêm một kiểm tra tương tự mỗi khi bạn định cấu hình nó.

Một số người có thể nghĩ rằng việc tạo một hàm kiểm tra cũng được mà, nhưng điều gì sẽ xảy ra nếu bạn quên code gọi chương trình con kiểm tra? Xem xét những thứ như vậy, tôi nghĩ chắc chắn hơn rằng bản thân đối tượng đã bao gồm việc kiểm tra trong nó.

Tính đóng gói làm tăng tính độc lập của lớp và cải thiện hiệu quả chỉnh sửa bằng cách sử dụng các thành viên chuyên dụng để truy cập dữ liệu.
Nói cách khác, nếu bạn muốn thay đổi cách dữ liệu được truy cập, tất cả những gì bạn phải làm là thay đổi lớp.

Nào, hãy tạo ra Module2 và dán code sau vào đó rồi chạy thử:
Module2:
Sub Encapsulation()
    Dim mySex As String
    With New clsPerson
        .Name = "Euler"
        .Age = 200          'Dua vao mot tuoi vo ly tren the gian nay
        .Sex = prSexFemale
        .Address = "HaNoi"
        GoSub PrintLbl
        .Name = " Ten linh tinh"      'Khong cho thiet dinh lai ten
        .Age = 30
        .Sex = prSexMale
        .Address = "Osaka"
        GoSub PrintLbl
        .Age = -5         'Dua vao mot tuoi vo ly tren the gian nay
        .Sex = 2          'Dua vao gioi tinh chua co dinh nghia trong Class
        .Address = "DaLat"
        GoSub PrintLbl
        Exit Sub
PrintLbl:
        If .Sex = prSexMale Then
            mySex = "Nam"
        Else
            mySex = "Nu"
        End If
        Debug.Print .Name, .Age & " Tuoi", mySex, .Address
        Return
    End With
End Sub
Bạn cần đăng nhập để thấy đính kèm

Như vậy xử lý lỗi đã đúng như ý đồ của chúng ta.
Nếu bạn không muốn đặt từng thuộc tính một, bạn có thể sử dụng phương pháp sau để thay thế.
Mã:
Public Sub SetIdentity( _
    Optional myNewName As String _
    , Optional ByVal myNewAge As Long = -1 _
    , Optional ByVal myNewSex As PrSex = -1 _
    , Optional myNewAddress As Variant)
    Name = myNewName
    Age = myNewAge
    Sex = myNewSex
    If IsMissing(myNewAddress) Then Exit Sub
    Address = CStr(myNewAddress)
End Sub
Cảm ơn bạn đã đọc bài viết dài.
Tôi không nghĩ rằng có nhiều trang web giới thiệu các mẫu sử dụng các lớp trong VBA, nhưng bằng cách học Class Module, bất cứ khi nào bạn phải gặp một ngôn ngữ lập trình khác, chắc chắn rằng nó sẽ hữu ích.

Trong mẫu này, có thể bạn không biết sử dụng nó vào việc gì, nhưng trong tương lai, tôi xin giới thiệu cách sử dụng Class Module được ứng dụng trong nhiều việc khác nhau.
Tham khảo và dịch từ :
 
Top