OOP_04
Just a note
Continue reading wOkO :P
OOP : Một cách giản lược, đây là khái niệm và là một nỗ lực nhằm giảm nhẹ các thao tác viết mã cho người lập trình, cho phép họ tạo ra các ứng dụng mà các yếu tố bên ngoài có thể tương tác với các chương trình đó giống như là tương tác với các đối tượng vật lý.
Ví dụ dưới đây thể hiện đầy đủ 4 tính chất của OOP.
#include <iostream>
using namespace std;
class myFriends {
private:
int bindValue;
public:
void setLevel(int n) { bindValue = n; }
int getLevel() { return bindValue; }
virtual void abstractClass () = 0;
};
class Male: myFriends {
private:
int countDayMet;
public:
using myFriends::setLevel;
void setDayMet(int n){ countDayMet = n; }
int getLevel(){ return myFriends::getLevel() * countDayMet; }
virtual void abstractClass(){};
// Virtual function nhưng đã hiện thực (mặc dù không có code trong block)
// vẫn hủy bỏ giá trị trừu tượng của một lớp
};
class Female: myFriends {
private:
int countDayMet;
public:
using myFriends::setLevel;
void setDayMet(int n){ countDayMet = n; }
int getLevel(){ return myFriends::getLevel() * countDayMet*2 + 50; }
virtual void abstractClass(){countDayMet = 0;}
// Tương tự hàm abtractClass ở trên, class này không còn tính trừu tượng.
int main(){
//myFriends Class12T1;
Male MinhHoang;
MinhHoang.setLevel(8);
MinhHoang.setDayMet(100);
Female DiepChi;
DiepChi.setLevel(4);
DiepChi.setDayMet(30);
Female BaoAn;
BaoAn.setLevel(6);
BaoAn.setDayMet(29);
cout << MinhHoang.getLevel() << endl;
cout << DiepChi.getLevel() << endl;
cout << BaoAn.getLevel() << endl;
return 0;
}
Tính trừu tượng:
Prob: Abstract Class
Trước hết, class myFriends là một Abstract Class. Vậy Abstract Class là gì, và liên quan gì đến tính đa hình của đoạn code trên.
Ans: Abstract Class
Ở class myFriends, hàm abstractClass là một pure virtual function,(indicated in the declaration with the syntax " = 0" in the member function's declaration) làm cho cả class myFriends trở thành một abstract class.
Những hàm abstractClass còn lại ở hai class Male và Famale không phải là pure abstract class (chỉ là một hàm virtual bình thường) nên không làm hai class này có tính trừu tượng
Ans: //myFriends Class12T1
Technically speaking, an abstract class is a class that cannot be directly instantiated. Instead, it is designed to be extended by concrete classes that can be instantiated. Abstract classes can— and typically do — define one or more abstract methods, which themselves do not contain a body. Instead, concrete subclasses are required to implement the abstract methods.
Let’s fabricate a quick example:
public abstract class Base {
public void doSomething() {
System.out.println("Doing something...")
}
public abstract void doSomethingElse();
}
Note that doSomething() – a non-abstract method – has implemented a body, while doSomethingElse() – an abstract method – has not. You cannot directly instantiate an instance of Base. Try this and your compiler will complain:
Base b = new Base();
Instead, you need to subclass Base, like so:
public class Sub extends Base {
public abstract void doSomethingElse() {
System.out.println("Doin' something else!");
}
}
Note the required implementation of the doSomethingElse() method.
Tương tự, khi chạy dòng đầu tiên ở hàm main myFriends Class12T1
compiler báo lỗi cannot declare variable 'Class12T1' to be of abstract type 'myFriends'
Prob: Hiểu về Abstract Class và Interface
Ans:
Đọc 2 bài viết dưới đây:
How to Choose Between Interface and Abstract Classes in Java
When to Use Abstract Class and Interface
Kết luận:
Consider using abstract classes if any of these statements apply to your situation:
- You want to share code among several closely related classes.\
- You expect that classes that extend your abstract class have many common methods or fields or require access modifiers other than public (such as protected and private).\
- You want to declare non-static or non-final fields. This enables you to define methods that can access and modify the state of the object to which they belong.
Consider using interfaces if any of these statements apply to your situation:
- You expect that unrelated classes would implement your interface. For example, the interfaces Comparable and Cloneable are implemented by many unrelated classes.\
- You want to specify the behavior of a particular data type, but not concerned about who implements its behavior.\
- You want to take advantage of multiple inheritances.\
Kết luận:
Vậy, tính trừu tượng ở đoạn code trên như sau:
i. Class myFriends là một abstract class, để khi nhìn vào một myFriend người code sẽ biết khái quát về các biến và các hàm cơ bản của một myFriend, từ đó có thể kế thừa và hiện thực tiếp.
ii. Người dùng (user) khi muốn xem Level của một người bạn chỉ cần setLevel và setDayMet, rồi dùng hàm getLevel(). Mà không biết rằng hàm getLevel lấy dữ liệu từ biến countDayMet (private) hay lấy tận biến bindValue ở class myFriends. So sánh với lập trình thủ tục, ví dụ khi gọi hàm getLevel, ta cần truyền vào các tham số (countDayMet, bindValue) cho hàm tính toán, nhưng bây giờ chỉ cần gọi getLevel(). Dễ gọi hơn, dễ hiểu hơn, và khi thay đổi code sau này, ví dụ thêm một biến private countGamesPlayedWith (đếm số game đã chơi chung) thì việc thay đổi công thức tính Level đơn giản hơn nhiều việc phải sửa toàn bộ code để truyền thêm biến countGamesPlayedWith vào.
Hay ví dụ hàm turnOn() trong một chiếc xe, trừu tượng hóa giúp người dùng chỉ cần chạy hàm turnOn() mà không cần quan tâm chiếc xe làm gì để khởi động. Việc này sẽ đơn giản hơn cho người dùng xe. Và khi phát triển thêm những tính năng để khởi động an toàn hơn, việc phát triển ấy sẽ đơn giản hơn nhiều.
iii. Dùng Abstract class ở đây (C++) chứ không phải một Pure abstract class (interface ở Java) vì class myFriends dùng để hiện thực tiếp các class Female và Male ở bên dưới
Tính đóng gói:
Các property bindValue và countDayMet thay vì chỉ là một biến tự do thì đã được đóng gói trong các class cùng với các method của class đó. Khi muốn set hay get các property đó, phải thông qua sự điều khiển của các hàm đã được hiện thực. Đồng thời làm rõ ràng hơn các thuộc tính của một class và quyền sử dụng các thuộc tính đó, mối quan hệ giữa các class với nhau. tránh việc sử dụng bừa bãi dẫn đến sai sót không mong muốn.
Tính kế thừa:
class Male và class Female đã kế thừa class myFriends hàm setLevel và override hàm getLevel với thuộc tính mới là countDayMet. Các object MinhHoang, DiepChi, BaoAn là các đối tượng được thực thể hóa từ hai class Male và Female đó và sử dụng được hàm setLevel vốn không hiện thực trong hai class này.
Tính đa hình:
Ta nói hàm getLevel() có tính đa hình, vì khi Object là MinhHoang, thuộc class Male, hàm getLevel thực hiện một phép tính khác với khi Object là DiepChi hay BaoAn thuộc class Female.
Việc sử dụng abstract class hay dễ thấy hơn là interface (vì interface dùng để hiện thực cho nhiều class hơn và do đó các method của interface tổng quát hơn, có nhiều tính đa hình hơn | xem lại 2 link ở Prob # tính trừu tượng) tạo nên tính đa hình. Cụ thể ở ví dụ này là hàm getLevel được tính khác nhau trên hai công thức dành cho bạn nữ và bạn nam.
Tham khảo:
- Vi - wiki
- When (Not) to Use Java Abstract Classes
- How to Choose Between Interface and Abstract Classes in Java
- When to Use Abstract Class and Interface
- What is Abstraction in OOPS?
- C++ wiki | Abstract Classes
Today:
- Đã đọc vi wiki
- Check lại nvim và chỉnh font terminal
Stuck tạiTrả lời được câu OOP_02#2#8 về abstract class và intreface- Trả lời OOP_02#1#4 về 4 tính chất OOP
Upcoming:
- Tiếp tục đọc hết 2 wiki
- Tiếp tục trả lời #OOP_02