ในการเขียนโปรแกรม วิปัสสนาและการไตร่ตรองเป็นแนวคิดที่เกี่ยวข้องกับการตรวจสอบและปรับเปลี่ยนโครงสร้างและพฤติกรรมของส่วนประกอบซอฟต์แวร์ในขณะรันไทม์

วิปัสสนา

วิปัสสนาคือความสามารถของโปรแกรมในการตรวจสอบโครงสร้างและคุณสมบัติของตัวเอง ด้วยการวิปัสสนา โปรแกรมสามารถเข้าถึงข้อมูลเกี่ยวกับตัวมันเองแบบไดนามิก เช่น ประเภทของออบเจ็กต์ วิธีที่มันสนับสนุน และคุณสมบัติที่มีอยู่ ซึ่งช่วยให้โปรแกรมสามารถปรับพฤติกรรมตามข้อมูลที่มีอยู่ ซึ่งมีประโยชน์อย่างยิ่งในสถานการณ์ที่เกี่ยวข้องกับการสร้างโค้ดแบบไดนามิก การทำให้เป็นอนุกรมของอ็อบเจ็กต์ การดีบัก และเฟรมเวิร์ก เช่น การทดสอบหน่วยหรือการฉีดการขึ้นต่อกัน

การสะท้อน

การสะท้อนกลับก้าวไปไกลกว่าการวิปัสสนาด้วยการอนุญาตให้โปรแกรมไม่เพียงแต่ตรวจสอบ แต่ยังปรับเปลี่ยนโครงสร้างและพฤติกรรมของตัวเองในขณะรันไทม์อีกด้วย ด้วยการสะท้อน โปรแกรมสามารถสร้างออบเจ็กต์ใหม่แบบไดนามิก เรียกใช้เมธอด เข้าถึงหรือแก้ไขฟิลด์ และแม้กระทั่งสร้างโค้ดแบบไดนามิก Reflection ให้ความสามารถในการดำเนินการเทคนิคเมตาโปรแกรมมิงที่มีประสิทธิภาพ ทำให้สามารถขยายฟังก์ชันการทำงานของโปรแกรม ใช้การปรับแต่ง หรือใช้คุณลักษณะที่ไม่มีอยู่ในเวลาคอมไพล์ อย่างไรก็ตาม สิ่งสำคัญที่ควรทราบก็คือ การสะท้อนกลับเป็นเครื่องมือที่ทรงพลังที่ควรใช้อย่างระมัดระวัง เนื่องจากสามารถเพิ่มความซับซ้อนและส่งผลต่อประสิทธิภาพได้หากใช้อย่างไม่เหมาะสม

ทั้งวิปัสสนาและการไตร่ตรองมักใช้ในภาษาที่พิมพ์แบบไดนามิก เช่น Python, Ruby และ JavaScript นำเสนอความยืดหยุ่นและไดนามิกในการทำงานของโปรแกรม ช่วยให้นักพัฒนาสามารถเขียนโค้ดทั่วไป ปรับเปลี่ยนได้ และขยายได้มากขึ้น

C++ ให้การสนับสนุนบางอย่างสำหรับการวิปัสสนาผ่านฟีเจอร์ต่างๆ เช่น ข้อมูลประเภท ซึ่งช่วยให้คุณดึงข้อมูลเกี่ยวกับประเภทต่างๆ ในเวลาคอมไพล์ได้ ตัวดำเนินการ typeid สามารถใช้เพื่อรับข้อมูลประเภทขณะรันไทม์ ช่วยให้คุณสามารถเปรียบเทียบประเภทหรือตรวจสอบชื่อได้ นอกจากนี้ คลาส std::type_info ยังมีฟังก์ชันพื้นฐานสำหรับการทำงานกับข้อมูลประเภท อย่างไรก็ตาม C++ ไม่มีความสามารถในการวิปัสสนาในตัว เช่น วิธีการเข้าถึงแบบไดนามิกหรือคุณสมบัติของอ็อบเจ็กต์

C++ ไม่มีความสามารถในการวิปัสสนาในตัว เช่น Python หรือ Java เนื่องจาก C++ เป็นภาษาที่พิมพ์แบบคงที่เป็นหลัก ซึ่งหมายความว่าลักษณะการทำงานส่วนใหญ่จะถูกกำหนด ณ เวลาคอมไพล์ ดังนั้นระดับของการวิปัสสนาและการไตร่ตรองที่มีอยู่ใน C ++ จึงมีข้อจำกัดมากกว่าเมื่อเทียบกับภาษาไดนามิก มีไลบรารีและเทคนิคที่สามารถอำนวยความสะดวกในรูปแบบการสะท้อนที่จำกัดใน C++ เช่น Boost.Reflection หรือโซลูชันของบริษัทอื่น อย่างไรก็ตาม โซลูชันเหล่านี้ไม่ได้ให้การวิปัสสนาและการไตร่ตรองในระดับเดียวกับภาษาไดนามิกเช่น Python หรือ Java

วิปัสสนากับ Qt

วิปัสสนาวัตถุเป็นคุณสมบัติที่มีประสิทธิภาพในกรอบงาน Qt ที่ช่วยให้คุณสามารถตรวจสอบและรวบรวมข้อมูลเกี่ยวกับวัตถุในขณะรันไทม์ ด้วยการใช้ความสามารถในการวิปัสสนาของ Qt คุณสามารถดึงข้อมูลรายละเอียด เช่น ชื่อคลาส คุณสมบัติ สัญญาณ และวิธีการของออบเจ็กต์ได้แบบไดนามิก

ในบทความนี้ เราจะสำรวจตัวอย่างที่สาธิตวิธีใช้วิปัสสนาใน Qt ลองพิจารณาตัวอย่างที่เรามีคลาส Person ที่ได้มาจาก QObject คลาส Person มีคุณสมบัติสองประการ: name และ age นอกจากนี้ยังกำหนดสัญญาณสองสัญญาณ: nameChanged และ ageChanged เป้าหมายคือการใช้วิปัสสนาเพื่อดึงข้อมูลเกี่ยวกับคุณสมบัติเหล่านี้และสัญญาณในขณะรันไทม์

บุคคล.h

#pragma once

#include <QObject>

class Person : public QObject
{
    Q_OBJECT

    Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
    Q_PROPERTY(int age READ getAge WRITE setAge NOTIFY ageChanged)
public:
    Person(QObject *parent = nullptr);
    virtual ~Person();
    QString getName() const { return m_name; }
    void    setName(const QString &name)
    {
        m_name = name;
        emit nameChanged();
    }
    int  getAge() const { return m_age; }
    void setAge(int age)
    {
        m_age = age;
        emit ageChanged();
    }
signals:
    void nameChanged();
    void ageChanged();

private:
    QString m_name;
    int     m_age;
};

main.cpp

#include <QCoreApplication>
#include <QDebug>
#include <QMetaObject>
#include <QMetaProperty>
#include <QMetaMethod>

#include "Person.h"

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    Person           obj;
    obj.setObjectName("myObject");

    // Get the meta-object of the object
    const QMetaObject *metaObject = obj.metaObject();

    // Get the class name
    QString className = metaObject->className();
    qDebug() << "Class Name:" << className;

    // Get the number of properties
    int propertyCount = metaObject->propertyCount();
    qDebug() << "Property Count:" << propertyCount;

    // Iterate over the properties
    for ( int i = 0; i < propertyCount; ++i )
    {
        QMetaProperty property = metaObject->property(i);
        qDebug() << "Property Name:" << property.name() << "Type:" << property.typeName()
                 << "Value:" << property.read(&obj);
    }

    // Get the number of methods
    int methodCount = metaObject->methodCount();
    qDebug() << "Method Count:" << methodCount;

    // Iterate over the methods
    for ( int i = 0; i < methodCount; ++i )
    {
        QMetaMethod method = metaObject->method(i);
        qDebug() << "Method Signature:" << method.methodSignature();
    }
    return app.exec();
}

ฟังก์ชัน main() แสดงให้เห็นถึงความสามารถในการวิปัสสนาโดยใช้คลาส QMetaObject เพื่อดึงข้อมูลเกี่ยวกับวัตถุในขณะรันไทม์

เมื่อคุณรันโค้ดนี้ มันจะแสดงผลดังต่อไปนี้:

Class Name: “Person”
Property Count: 3
Property Name: objectName Type: QString Value: QVariant(QString, “myObject”)
Property Name: name Type: QString Value: QVariant(QString, “”)
Property Name: age Type: int Value: QVariant(int, 0)
Method Count: 7
Method Signature: “destroyed(QObject*)”
Method Signature: “destroyed()”
Method Signature: “objectNameChanged(QString)”
Method Signature: “deleteLater()”
Method Signature: “_q_reregisterTimers(void*)”
Method Signature: “nameChanged()”
Method Signature: “ageChanged()”

อย่างที่คุณเห็น โค้ดจะดึงชื่อคลาส จำนวนคุณสมบัติ ชื่อคุณสมบัติ ประเภท และค่า ตลอดจนลายเซ็นของเมธอด สิ่งนี้แสดงให้เห็นว่าวิปัสสนาช่วยให้คุณสามารถตรวจสอบและรวบรวมข้อมูลเกี่ยวกับคุณสมบัติของวัตถุและวิธีการแบบไดนามิก ณ รันไทม์ได้อย่างไร

สามารถดาวน์โหลดซอร์สโค้ดสำหรับบทความนี้ได้จาก: