Dalam pemrograman, introspeksi dan refleksi adalah konsep yang melibatkan pemeriksaan dan modifikasi struktur dan perilaku komponen perangkat lunak saat runtime.
Introspeksi
Introspeksi adalah kemampuan suatu program untuk memeriksa struktur dan propertinya sendiri. Melalui introspeksi, suatu program dapat secara dinamis mengakses informasi tentang dirinya sendiri, seperti jenis suatu objek, metode yang didukungnya, dan properti yang dimilikinya. Hal ini memungkinkan program untuk menyesuaikan perilakunya berdasarkan informasi yang tersedia, yang sangat berguna dalam skenario yang melibatkan pembuatan kode dinamis, serialisasi objek, debugging, dan kerangka kerja seperti pengujian unit atau injeksi ketergantungan.
Cerminan
Refleksi melangkah lebih jauh dari introspeksi dengan memungkinkan suatu program tidak hanya memeriksa tetapi juga memodifikasi struktur dan perilakunya sendiri pada waktu proses. Dengan refleksi, suatu program dapat secara dinamis membuat objek baru, memanggil metode, mengakses atau memodifikasi bidang, dan bahkan menghasilkan kode secara dinamis. Refleksi memberikan kemampuan untuk melakukan teknik metaprogramming yang kuat, sehingga memungkinkan untuk memperluas fungsionalitas program, menerapkan penyesuaian, atau mengimplementasikan fitur yang tidak ada pada waktu kompilasi. Namun, penting untuk dicatat bahwa refleksi adalah alat yang ampuh yang harus digunakan dengan hati-hati, karena dapat meningkatkan kompleksitas dan mempengaruhi kinerja jika digunakan secara tidak tepat.
Introspeksi dan refleksi umumnya digunakan dalam bahasa yang diketik secara dinamis seperti Python, Ruby, dan JavaScript. Mereka menawarkan fleksibilitas dan dinamisme dalam eksekusi program, memungkinkan pengembang untuk menulis kode yang lebih umum, mudah beradaptasi, dan diperluas.
C++ menyediakan beberapa dukungan untuk introspeksi melalui fitur seperti informasi tipe, yang memungkinkan Anda mengambil informasi tentang tipe pada waktu kompilasi. Operator typeid
dapat digunakan untuk mendapatkan informasi tipe saat runtime, memungkinkan Anda membandingkan tipe atau memeriksa namanya. Selain itu, kelas std::type_info
menyediakan fungsionalitas dasar untuk bekerja dengan informasi tipe. Namun, C++ tidak menyediakan kemampuan introspeksi bawaan yang ekstensif seperti mengakses metode atau properti objek secara dinamis.
C++ tidak menyediakan kemampuan introspeksi bawaan yang ekstensif seperti Python atau Java. Hal ini karena C++ pada dasarnya adalah bahasa yang diketik secara statis, yang berarti bahwa sebagian besar perilakunya ditentukan pada waktu kompilasi. Oleh karena itu, tingkat introspeksi dan refleksi yang tersedia dalam C++ lebih terbatas dibandingkan dengan bahasa dinamis. Ada perpustakaan dan teknik yang dapat memfasilitasi bentuk refleksi terbatas dalam C++, seperti Boost.Reflection atau solusi pihak ketiga. Namun, solusi ini tidak memberikan tingkat introspeksi dan refleksi yang sama seperti bahasa dinamis seperti Python atau Java.
Introspeksi dengan Qt
Introspeksi objek adalah fitur canggih dalam kerangka Qt yang memungkinkan Anda memeriksa dan mengumpulkan informasi tentang objek saat runtime. Dengan menggunakan kemampuan introspeksi Qt, Anda dapat mengambil detail seperti nama kelas, properti, sinyal, dan metode suatu objek secara dinamis.
Pada artikel ini, kita akan mengeksplorasi contoh yang menunjukkan cara menggunakan introspeksi di Qt. Mari kita perhatikan contoh di mana kita memiliki kelas Person
yang berasal dari QObject
. Kelas Person
memiliki dua properti: name
dan age
. Selain itu, ini juga mendefinisikan dua sinyal: nameChanged
dan ageChanged
. Tujuannya adalah menggunakan introspeksi untuk mengambil informasi tentang properti dan sinyal ini pada waktu proses.
Orang.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; };
utama.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(); }
Fungsi main() mendemonstrasikan kemampuan introspeksi dengan menggunakan kelas QMetaObject untuk mengambil informasi tentang objek saat runtime.
Saat Anda menjalankan kode ini, hasilnya akan seperti berikut:
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()”
Seperti yang Anda lihat, kode tersebut mengambil nama kelas, jumlah properti, nama properti, tipe, dan nilai, serta tanda tangan metode. Ini menunjukkan bagaimana introspeksi memungkinkan Anda memeriksa dan mengumpulkan informasi tentang properti dan metode objek secara dinamis saat runtime.
Kode sumber artikel ini dapat diunduh dari: