Kotlin এর Annotations এবং Reflection
কটলিনে Annotations এবং Reflection দুটি শক্তিশালী ফিচার যা কোডের মেটাডেটা নিয়ে কাজ করতে এবং কোডের কার্যকারিতা উন্নত করতে সহায়ক। Annotations ব্যবহার করে আপনি ক্লাস, ফাংশন, প্রপার্টি ইত্যাদিতে মেটাডেটা যোগ করতে পারেন এবং Reflection ব্যবহার করে runtime এ অবজেক্টের বৈশিষ্ট্য এবং আচরণ নিয়ে কাজ করতে পারেন। নিচে Annotations এবং Reflection নিয়ে বিস্তারিত আলোচনা করা হলো।
১. Annotations
Annotations কটলিনে বিশেষ মার্কআপ যা কোডের মেটাডেটা যুক্ত করতে ব্যবহৃত হয়। এটি একটি ক্লাস, ফাংশন, প্রপার্টি, ইত্যাদিতে প্রয়োগ করা যায় এবং এটি বিভিন্ন উদ্দেশ্যে ব্যবহার করা হয়, যেমন: ডকুমেন্টেশন, লেআউট ইনফরমেশন, বা কোড গুণগত মান যাচাই।
i) Annotation তৈরি করা
Annotations তৈরি করতে annotation class কিওয়ার্ড ব্যবহার করা হয়।
উদাহরণ:
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class MyCustomAnnotation(val description: String)
ব্যাখ্যা:
- এখানে
MyCustomAnnotationএকটি কাস্টম অ্যানোটেশন যাCLASSএবংFUNCTIONএ প্রয়োগ করা যাবে। এটি runtime এ উপলব্ধ থাকবে।
ii) Annotation প্রয়োগ করা
Annotations ক্লাস বা ফাংশনে প্রয়োগ করা যায়।
উদাহরণ:
@MyCustomAnnotation(description = "This is a sample class")
class SampleClass {
@MyCustomAnnotation(description = "This is a sample function")
fun sampleFunction() {
println("Function is called.")
}
}
২. Reflection
Reflection হলো একটি প্রক্রিয়া যা runtime এ অবজেক্টের প্রপার্টি এবং মেথডের তথ্য সংগ্রহ এবং ব্যবহার করতে সহায়তা করে। কটলিনে Reflection ব্যবহার করে আপনি ক্লাস, মেথড, প্রপার্টি ইত্যাদি সম্পর্কে তথ্য পেতে পারেন।
i) Reflection ব্যবহার করা
কটলিনে Reflection এর মাধ্যমে ক্লাসের তথ্য পাওয়া যায়।
উদাহরণ:
fun main() {
val sampleClass = SampleClass::class // Getting KClass reference
println("Class name: ${sampleClass.simpleName}")
val methods = sampleClass.members
methods.forEach { println("Method: ${it.name}") } // Listing methods
}
ব্যাখ্যা:
- এখানে
SampleClass::classব্যবহার করেKClassএর একটি রেফারেন্স পাওয়া হয়েছে এবং ক্লাসের নাম এবং মেথডগুলো তালিকাভুক্ত করা হয়েছে।
ii) Annotations এর Reflection
Reflection ব্যবহার করে আপনি annotations এর তথ্যও পেতে পারেন।
উদাহরণ:
fun main() {
val sampleClass = SampleClass::class
val annotation = sampleClass.annotations.find { it is MyCustomAnnotation } as? MyCustomAnnotation
println("Annotation description: ${annotation?.description}") // আউটপুট: Annotation description: This is a sample class
}
ব্যাখ্যা:
- এখানে
SampleClassএর অ্যানোটেশনগুলি যাচাই করা হয়েছে এবংMyCustomAnnotationএর বিবরণ বের করা হয়েছে।
উপসংহার
কটলিনের Annotations এবং Reflection কোডের মেটাডেটা নিয়ে কাজ করতে এবং runtime এ অবজেক্টের বৈশিষ্ট্য ও আচরণ বিশ্লেষণ করতে সহায়ক। Annotations বিভিন্ন উদ্দেশ্যে ব্যবহার করা যায়, এবং Reflection runtime এ কোডের বৈশিষ্ট্য সম্বন্ধে গভীর তথ্য প্রদান করে। এই ফিচারগুলো ব্যবহার করে আপনি আরও উন্নত এবং দৃষ্টিনন্দন কোড তৈরি করতে পারবেন।
Annotations কী এবং কেন গুরুত্বপূর্ণ
Annotations কটলিনসহ অনেক প্রোগ্রামিং ভাষায় ব্যবহৃত একটি শক্তিশালী ফিচার, যা কোডে অতিরিক্ত তথ্য বা মেটাডেটা যোগ করার জন্য ব্যবহৃত হয়। এগুলো মূলত ক্লাস, মেথড, প্রপার্টি, বা ফাংশনের উপর বিশেষ বৈশিষ্ট্য চিহ্নিত করতে ব্যবহৃত হয়। নিচে Annotations-এর ধারণা, গুরুত্বপূর্ণতা এবং কিভাবে কাজ করে তা বিস্তারিতভাবে আলোচনা করা হলো।
১. Annotations কী?
Annotations হলো বিশেষ ধরনের ট্যাগ বা মেটাডেটা যা কোডের বিভিন্ন অংশে যুক্ত করা হয়। এগুলো কম্পাইলার বা রানটাইমের জন্য অতিরিক্ত নির্দেশিকা হিসেবে কাজ করে, কিন্তু এগুলো কোডের কার্যকরী অংশ নয়। কটলিনে, annotations @ সিম্বল দিয়ে শুরু হয়।
উদাহরণ:
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class MyCustomAnnotation(val description: String)
@MyCustomAnnotation("This is a custom annotation")
fun annotatedFunction() {
println("This function is annotated")
}
ব্যাখ্যা:
- এখানে
MyCustomAnnotationএকটি কাস্টম annotation, যা@Targetদ্বারা নির্দেশ করা হয়েছে যে এটি একটি ফাংশনে ব্যবহার করা যাবে এবং@Retentionদ্বারা নির্দেশ করা হয়েছে যে এটি রানটাইমে উপলব্ধ থাকবে।
২. Annotations এর প্রকারভেদ
কটলিনে বিভিন্ন ধরনের annotations ব্যবহৃত হয়, যেমন:
i) Built-in Annotations
- @Deprecated: এটি নির্দেশ করে যে একটি ফাংশন বা ক্লাস ব্যবহার করা উচিত নয়, কারণ এটি ভবিষ্যতে বাদ পড়তে পারে।
@Deprecated("Use newFunction() instead")
fun oldFunction() {
// Implementation
}
- @JvmStatic: এটি নির্দেশ করে যে একটি স্ট্যাটিক ফাংশন কিভাবে Java এর সাথে কাজ করবে।
ii) Custom Annotations
- আপনি নিজের কাস্টম annotations তৈরি করতে পারেন, যেমন উপরে উল্লেখিত উদাহরণে
MyCustomAnnotationতৈরি করা হয়েছে।
৩. Annotations এর গুরুত্বপূর্ণতা
i) Metadata for Code
Annotations কোডে অতিরিক্ত তথ্য বা মেটাডেটা প্রদান করে, যা কোডের উদ্দেশ্য বা কার্যকলাপ বোঝাতে সাহায্য করে। এটি ডেভেলপারদের জন্য কোড পড়া এবং বুঝতে সহজ করে।
ii) Compile-time and Runtime Checks
Annotations ব্যবহার করে বিভিন্ন চেকিং করা যায়। উদাহরণস্বরূপ, @NotNull ব্যবহার করে null safety নিশ্চিত করা যায়।
iii) Frameworks and Libraries
বিভিন্ন ফ্রেমওয়ার্ক এবং লাইব্রেরি annotations ব্যবহার করে তাদের কার্যকারিতা নির্ধারণ করে। উদাহরণস্বরূপ, Spring ফ্রেমওয়ার্কে DI (Dependency Injection) এর জন্য annotations ব্যবহার করা হয়।
iv) Code Generation
Annotations ব্যবহার করে কোড জেনারেশন করা যেতে পারে। যেমন, কিছু লাইব্রেরি runtime এ annotations পড়ে কোড তৈরি করে।
৪. Annotations কিভাবে কাজ করে?
Annotations কিভাবে কাজ করে তা বোঝার জন্য, নিচে একটি উদাহরণ দেওয়া হলো যেখানে @Target এবং @Retention ব্যবহার করা হয়েছে।
উদাহরণ:
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class Entity(val tableName: String)
@Entity(tableName = "users")
class User(val id: Int, val name: String)
fun main() {
val userClass = User::class
val annotation = userClass.annotations.find { it is Entity } as? Entity
println("Table Name: ${annotation?.tableName}") // আউটপুট: Table Name: users
}
ব্যাখ্যা:
- এখানে
Entityannotation তৈরি করা হয়েছে, যা ক্লাসে ব্যবহার করা যায় এবং রানটাইমে উপলব্ধ থাকবে।Userক্লাসের উপর এই annotation ব্যবহার করে আমরা একটি টেবিলের নাম সংরক্ষণ করেছি, যা পরে কোডের মধ্যে পড়া যাবে।
উপসংহার
Annotations কটলিনের একটি গুরুত্বপূর্ণ ফিচার যা কোডে মেটাডেটা যোগ করতে এবং বিভিন্ন কার্যকলাপ চিহ্নিত করতে ব্যবহৃত হয়। এগুলো কোডের পাঠযোগ্যতা, ফ্রেমওয়ার্ক ও লাইব্রেরি উন্নত করার ক্ষেত্রে সহায়ক, এবং runtime বা compile-time চেকিং সহজ করে। কাস্টম annotations তৈরি করে আপনি আপনার কোডের কার্যকারিতা বাড়াতে পারেন।
Built-in এবং Custom Annotations তৈরি
কটলিনে Annotations একটি গুরুত্বপূর্ণ ফিচার, যা কোডের বিভিন্ন অংশকে মেটাডেটা প্রদান করে। এটি কম্পাইলার, রানটাইম বা লাইব্রেরি দ্বারা বিশেষভাবে ব্যবহার করা হয়। Built-in annotations যেমন @Deprecated, @Override, এবং @JvmField ইতোমধ্যে কটলিনে বিদ্যমান। Custom annotations তৈরি করে আপনি আপনার প্রয়োজন অনুযায়ী নতুন মেটাডেটা তৈরি করতে পারেন। নিচে Built-in এবং Custom Annotations সম্পর্কে বিস্তারিত আলোচনা করা হলো।
১. Built-in Annotations
কটলিনে কিছু Built-in annotations রয়েছে, যা সাধারণত কিছু নির্দিষ্ট কার্যকারিতার জন্য ব্যবহৃত হয়।
i) @Deprecated
@Deprecated annotation একটি এলিমেন্ট বা ফাংশনকে চিহ্নিত করে যে এটি ব্যবহৃত হতে পারে কিন্তু এটি আর সুপারিশ করা হয় না এবং ভবিষ্যতে সরিয়ে ফেলা হতে পারে।
উদাহরণ:
@Deprecated("Use newFunction() instead", ReplaceWith("newFunction()"))
fun oldFunction() {
println("This is an old function.")
}
fun newFunction() {
println("This is the new function.")
}
fun main() {
oldFunction() // এটি একটি ডিপ্রিকেটেড ফাংশন কল করবে
}
ব্যাখ্যা:
- এখানে
oldFunctionডিপ্রিকেটেড, এবং এর পরিবর্তেnewFunctionব্যবহারের জন্য সুপারিশ করা হয়েছে।
ii) @JvmField
@JvmField annotation ব্যবহার করে আপনি কটলিন প্রোপার্টি প্রকাশ করতে পারেন যাতে এটি সরাসরি জাভা ফিল্ড হিসেবে ব্যবহার করা যায়। এটি কটলিনের getter/setter অতিক্রম করে।
উদাহরণ:
class Example {
@JvmField
var number: Int = 10
}
ব্যাখ্যা:
- এখানে
@JvmFieldব্যবহার করেnumberপ্রোপার্টিটি জাভা ফিল্ড হিসেবে প্রকাশ করা হয়েছে, ফলে জাভা থেকে সরাসরি এটি অ্যাক্সেস করা যাবে।
২. Custom Annotations
Custom annotations তৈরি করতে, আপনাকে annotation টাইপ ঘোষণা করতে হবে। কটলিনে, @Target, @Retention, এবং অন্যান্য মেটাডেটা ব্যবহার করে annotation কাস্টমাইজ করা যায়।
i) Custom Annotation তৈরি
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class MyCustomAnnotation(val info: String)
ব্যাখ্যা:
@Targetব্যবহার করে আপনি চিহ্নিত করতে পারেন যে এই annotation কোন ধরনের এলিমেন্টে ব্যবহার করা যাবে (যেমন ক্লাস, ফাংশন, প্রোপার্টি)।@Retentionব্যবহার করে চিহ্নিত করা হয় যে annotation কবে পর্যন্ত ধরে রাখা হবে (যেমন SOURCE, BINARY, RUNTIME)।
ii) Custom Annotation ব্যবহার
@MyCustomAnnotation("This is a custom annotation")
class MyClass {
@MyCustomAnnotation("Method annotation")
fun myFunction() {
println("Function with custom annotation.")
}
}
ব্যাখ্যা:
- এখানে
MyClassএবংmyFunctionএMyCustomAnnotationব্যবহার করা হয়েছে।
iii) Custom Annotation-এর তথ্য পড়া
Custom annotation ব্যবহার করে যে তথ্য পড়া যায়, তার উদাহরণ:
fun main() {
val annotations = MyClass::class.annotations
for (annotation in annotations) {
if (annotation is MyCustomAnnotation) {
println("Class annotation info: ${annotation.info}")
}
}
val method = MyClass::class.java.methods.first()
val methodAnnotations = method.annotations
for (annotation in methodAnnotations) {
if (annotation is MyCustomAnnotation) {
println("Method annotation info: ${annotation.info}")
}
}
}
ব্যাখ্যা:
- এখানে
MyClassএর উপর লাগানো annotation-এর তথ্য পড়া হয়েছে এবংmyFunctionএর annotation সম্পর্কে তথ্য বের করা হয়েছে।
উপসংহার
কটলিনে Built-in এবং Custom Annotations কোডে মেটাডেটা যোগ করতে ব্যবহৃত হয়, যা প্রোগ্রামিংয়ের বিভিন্ন প্রেক্ষাপটে কাজ করে। Built-in annotations যেমন @Deprecated এবং @JvmField ডেভেলপমেন্টে সাহায্য করে, যখন Custom annotations আপনার নিজস্ব মেটাডেটা তৈরি করতে এবং ব্যবহারে সহায়তা করে।
Reflection API এবং Class Introspection
কটলিনের Reflection API এবং Class Introspection আপনাকে কোডের মেটাডেটা বিশ্লেষণ এবং অবজেক্টের সম্পর্কে বিস্তারিত তথ্য জানতে সাহায্য করে। Reflection API ব্যবহার করে, আপনি ক্লাস, প্রপার্টি, ফাংশন এবং অ্যানোটেশনগুলি নিয়ে কাজ করতে পারেন, যা runtime এ কোডের কার্যকারিতা উন্নত করতে পারে। নিচে Reflection API এবং Class Introspection নিয়ে বিস্তারিত আলোচনা করা হলো।
১. Reflection API
Reflection API কটলিনে কোডের বিভিন্ন বৈশিষ্ট্য এবং আচরণ সম্পর্কে তথ্য সংগ্রহ করতে ব্যবহৃত হয়। এটি kotlin.reflect প্যাকেজে অন্তর্ভুক্ত এবং এর মাধ্যমে আপনি ক্লাসের মেটাডেটা এবং অবজেক্টের স্টেট পরিবর্তন করতে পারেন।
i) KClass
KClass একটি ক্লাসের তথ্য উপস্থাপন করে।
উদাহরণ:
import kotlin.reflect.full.*
class Person(val name: String, val age: Int)
fun main() {
val personClass = Person::class // Getting KClass reference
println("Class Name: ${personClass.simpleName}") // আউটপুট: Class Name: Person
// Listing member properties
val properties = personClass.memberProperties
properties.forEach { println("Property: ${it.name}") }
}
ব্যাখ্যা:
- এখানে
Person::classব্যবহার করেKClassএর একটি রেফারেন্স পাওয়া গেছে এবং ক্লাসের নাম ও প্রপার্টি তালিকাভুক্ত করা হয়েছে।
২. Class Introspection
Class Introspection Reflection API ব্যবহার করে ক্লাসের সদস্যদের সম্পর্কে তথ্য সংগ্রহ করার প্রক্রিয়া। এটি আপনাকে ক্লাসের প্রপার্টি, মেথড, কনস্ট্রাকটর ইত্যাদি সম্পর্কে বিস্তারিত জানতে দেয়।
i) Class Members
ক্লাসের সদস্যদের তালিকা বের করা।
উদাহরণ:
class Vehicle(val make: String, val model: String) {
fun start() = "Starting $make $model"
}
fun main() {
val vehicleClass = Vehicle::class
// Get constructors
val constructors = vehicleClass.constructors
constructors.forEach { println("Constructor: ${it.parameters}") }
// Get member functions
val functions = vehicleClass.memberFunctions
functions.forEach { println("Function: ${it.name}") }
}
ব্যাখ্যা:
- এখানে
constructorsএবংmemberFunctionsব্যবহার করেVehicleক্লাসের কনস্ট্রাকটর এবং মেথডের তথ্য পাওয়া গেছে।
৩. Accessing Property Values
Reflection API ব্যবহার করে আপনি ক্লাসের প্রপার্টির মানও অ্যাক্সেস করতে পারেন।
উদাহরণ:
fun main() {
val vehicle = Vehicle("Toyota", "Corolla")
val vehicleClass = vehicle::class
// Accessing property values
val makeProperty = vehicleClass.memberProperties.find { it.name == "make" }
println("Vehicle Make: ${makeProperty?.get(vehicle)}") // আউটপুট: Vehicle Make: Toyota
}
ব্যাখ্যা:
- এখানে
memberPropertiesথেকেmakeপ্রপার্টির মান অ্যাক্সেস করা হয়েছে।
৪. Using Annotations with Reflection
Reflection API ব্যবহার করে আপনি অ্যানোটেশন সম্পর্কিত তথ্যও পেতে পারেন।
উদাহরণ:
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class Description(val info: String)
@Description("This class represents a book")
class Book(val title: String)
fun main() {
val bookClass = Book::class
val annotation = bookClass.annotations.find { it is Description } as? Description
println("Book Description: ${annotation?.info}") // আউটপুট: Book Description: This class represents a book
}
ব্যাখ্যা:
- এখানে
Descriptionনামে একটি কাস্টম অ্যানোটেশন তৈরি করা হয়েছে এবংBookক্লাসে প্রয়োগ করা হয়েছে। Reflection API ব্যবহার করে অ্যানোটেশনটির তথ্য বের করা হয়েছে।
উপসংহার
কটলিনের Reflection API এবং Class Introspection কোডের মেটাডেটা বিশ্লেষণ এবং অবজেক্টের আচরণ সম্পর্কে গভীর তথ্য সংগ্রহ করতে সহায়ক। এটি কোডের ডায়নামিক আচরণ বোঝার জন্য এবং অ্যাপ্লিকেশনগুলিতে গতিশীল কার্যক্রম পরিচালনার জন্য অত্যন্ত কার্যকর।
Annotations ব্যবহার করে কোড মডিফাই করা
কটলিনে Annotations ব্যবহারের মাধ্যমে আপনি আপনার কোডে মেটাডেটা যুক্ত করতে পারেন এবং এই তথ্যের ভিত্তিতে আপনার কোডের আচরণ পরিবর্তন করতে পারেন। এই পদ্ধতিটি বিশেষ করে ডেভেলপারদের জন্য সাহায্যকারী যন্ত্র হিসেবে কাজ করে, যা বিভিন্ন কাজ সম্পন্ন করতে এবং সঠিক কাজগুলি পরিচালনা করতে সহায়তা করে। নিচে Annotations ব্যবহার করে কোড মডিফাই করার প্রক্রিয়া এবং উদাহরণ দেওয়া হলো।
১. Annotation তৈরি করা
Annotations তৈরি করতে, আপনাকে annotation class কিওয়ার্ড ব্যবহার করতে হবে। এখানে একটি কাস্টম Annotation উদাহরণ দেওয়া হলো।
i) Annotation Definition
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class LogExecution(val message: String)
ব্যাখ্যা:
- এখানে
LogExecutionনামে একটি Annotation তৈরি করা হয়েছে যাFUNCTIONটার্গেটের জন্য এবং runtime এ উপলব্ধ থাকবে।
২. Annotation প্রয়োগ করা
এখন আমরা আমাদের Annotation টি একটি ফাংশনে প্রয়োগ করব।
ii) Annotation Application
class Calculator {
@LogExecution("Executing addition")
fun add(a: Int, b: Int): Int {
return a + b
}
}
ব্যাখ্যা:
- এখানে
addফাংশনের উপরে@LogExecutionAnnotation প্রয়োগ করা হয়েছে, যা যখন এই ফাংশনটি কল করা হবে তখন একটি বার্তা প্রদান করবে।
৩. Annotation Processing
Annotations ব্যবহারের পরে, আপনাকে runtime এ তাদের তথ্য প্রক্রিয়া করতে হবে। কটলিনে Reflection API ব্যবহার করে আপনি Annotation থেকে তথ্য সংগ্রহ করতে পারেন।
iii) Annotation Processing Example
import kotlin.reflect.full.*
fun main() {
val calculator = Calculator()
val function = calculator::class.members.find { it.name == "add" }
// Check for the LogExecution annotation
function?.annotations?.forEach { annotation ->
if (annotation is LogExecution) {
println("Annotation message: ${annotation.message}")
}
}
// Call the add function
val result = calculator.add(5, 3)
println("Result of addition: $result") // আউটপুট: Result of addition: 8
}
ব্যাখ্যা:
- এখানে আমরা
Calculatorক্লাসেরaddফাংশনের জন্যLogExecutionAnnotation এর তথ্য যাচাই করেছি এবং তার পরে সেই ফাংশনটি কল করেছি। Annotation থেকে একটি বার্তা প্রিন্ট করা হয়েছে।
৪. Annotations দ্বারা কোডের আচরণ পরিবর্তন করা
Annotations ব্যবহার করে কোডের আচরণ পরিবর্তন করার জন্য, আপনি ডাইনামিকভাবে ফাংশনগুলির কার্যকারিতা পরিবর্তন করতে পারেন। নিচে একটি উদাহরণ দেওয়া হলো যেখানে Annotation এর ভিত্তিতে একটি ফাংশনের কার্যকারিতা পরিবর্তন করা হচ্ছে।
iv) Dynamic Behavior Change Example
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class RequiresAdmin
class User(val role: String) {
@RequiresAdmin
fun adminFunction() {
println("Admin function executed.")
}
fun performAction(action: () -> Unit) {
// Check if the action requires admin rights
val requiresAdmin = action::class.annotations.any { it is RequiresAdmin }
if (requiresAdmin && role != "Admin") {
println("Access denied. Admin rights required.")
} else {
action()
}
}
}
fun main() {
val user = User("User")
// Trying to call the admin function
user.performAction { user.adminFunction() } // আউটপুট: Access denied. Admin rights required.
// Changing user role to Admin
val adminUser = User("Admin")
adminUser.performAction { adminUser.adminFunction() } // আউটপুট: Admin function executed.
}
ব্যাখ্যা:
- এখানে
Userক্লাসে একটিadminFunctionআছে, যা@RequiresAdminAnnotation দ্বারা চিহ্নিত।performActionফাংশনটি আগে থেকে নির্ধারিত কার্যক্রমের জন্য একটি প্যারামিটার গ্রহণ করে এবং চেক করে যে ঐ কার্যক্রমটি প্রশাসক অধিকার প্রয়োজন কিনা। - যদি
role"Admin" না হয়, তাহলে এটি "Access denied" বার্তা দেখায়।
উপসংহার
কটলিনে Annotations ব্যবহার করে কোড মডিফাই করা একটি শক্তিশালী কৌশল। এটি আপনাকে কোডে মেটাডেটা যুক্ত করতে এবং runtime এ কোডের আচরণ পরিবর্তন করতে সক্ষম করে। Annotations ব্যবহারের মাধ্যমে আপনি আপনার কোডের কার্যকারিতা এবং নিয়ন্ত্রণ বৃদ্ধি করতে পারেন।
Read more