JavaRush /جاوا بلاگ /Random-UR /جاوا @ تشریحات۔ یہ کیا ہے اور اسے کیسے استعمال کیا جائے؟
SemperAnte
سطح
Донецк

جاوا @ تشریحات۔ یہ کیا ہے اور اسے کیسے استعمال کیا جائے؟

گروپ میں شائع ہوا۔
یہ مضمون ان لوگوں کے لیے ہے جنہوں نے تشریحات کے ساتھ کبھی کام نہیں کیا، لیکن وہ یہ سمجھنا چاہتے ہیں کہ یہ کیا ہے اور اس کے ساتھ استعمال کیا جاتا ہے۔ اگر آپ کو اس شعبے میں تجربہ ہے، تو مجھے نہیں لگتا کہ یہ مضمون کسی طرح آپ کے علم میں اضافہ کرے گا (اور درحقیقت، میں ایسے کسی مقصد کا تعاقب نہیں کرتا)۔ اس کے علاوہ، مضمون ان لوگوں کے لیے موزوں نہیں ہے جو ابھی جاوا زبان سیکھنا شروع کر رہے ہیں۔ اگر آپ یہ نہیں سمجھتے کہ Map<> یا HashMap<> کیا ہے یا نہیں جانتے کہ کلاس ڈیفینیشن کے اندر static{ } اندراج کا کیا مطلب ہے، یا آپ نے کبھی عکاسی کے ساتھ کام نہیں کیا ہے، تو آپ کے لیے یہ مضمون پڑھنا بہت جلد ہے اور یہ سمجھنے کی کوشش کریں کہ تشریحات کیا ہیں۔ یہ ٹول بذات خود ابتدائی افراد کے استعمال کے لیے نہیں بنایا گیا ہے، کیوں کہ اس کے لیے کلاسز اور اشیاء کے تعامل کی مکمل طور پر بنیادی تفہیم کی ضرورت نہیں ہے (میری رائے) (اس پوسٹ اسکرپٹ کی ضرورت ظاہر کرنے کے لیے تبصروں کا شکریہ)۔ جاوا @ تشریحات۔  یہ کیا ہے اور اسے کیسے استعمال کیا جائے؟  - 1تو آئیے شروع کرتے ہیں۔ جاوا میں تشریحات کوڈ میں ایک قسم کے لیبل ہیں جو فنکشن/کلاس/پیکیج کے لیے میٹا ڈیٹا کی وضاحت کرتے ہیں۔ مثال کے طور پر، معروف @Override تشریح، جو اس بات کی نشاندہی کرتی ہے کہ ہم پیرنٹ کلاس کے طریقہ کو اوور رائیڈ کرنے جا رہے ہیں۔ جی ہاں، ایک طرف، یہ اس کے بغیر ممکن ہے، لیکن اگر والدین کے پاس یہ طریقہ نہیں ہے، تو اس بات کا امکان ہے کہ ہم نے کوڈ کو بیکار لکھا ہے، کیونکہ اس مخصوص طریقہ کو کبھی نہیں کہا جا سکتا ہے، لیکن @Override تشریح کے ساتھ کمپائلر ہمیں بتائے گا کہ: "مجھے والدین میں ایسا طریقہ نہیں ملا... یہاں کچھ گندا ہے۔" تاہم، تشریحات صرف "قابل اعتماد" کے معنی نہیں لے سکتی ہیں: وہ کچھ ڈیٹا محفوظ کر سکتے ہیں جو بعد میں استعمال کیا جائے گا۔

سب سے پہلے، معیاری لائبریری کی طرف سے فراہم کردہ آسان ترین تشریحات کو دیکھتے ہیں۔

(تبصروں کا ایک بار پھر شکریہ، پہلے میں نے نہیں سوچا کہ اس بلاک کی ضرورت ہے) پہلے، آئیے اس بات پر بات کرتے ہیں کہ تشریحات کیا ہیں۔ ان میں سے ہر ایک کے پاس 2 اہم ضروری پیرامیٹرز ہیں:
  • اسٹوریج کی قسم (برقرار)؛
  • آبجیکٹ کی وہ قسم جس پر اس کی نشاندہی کی گئی ہے (ٹارگٹ)۔

اسٹوریج کی قسم

"اسٹوریج کی قسم" سے ہمارا مطلب وہ مرحلہ ہے جس میں کلاس کے اندر ہماری تشریح "بقت رکھتی ہے"۔ ہر تشریح میں RetentionPolicy کلاس میں مخصوص "برقرار رکھنے کی ممکنہ اقسام" میں سے صرف ایک ہوتی ہے :
  • ماخذ - تشریح صرف کوڈ لکھتے وقت استعمال ہوتی ہے اور مرتب کرنے والے کے ذریعہ نظر انداز کیا جاتا ہے (یعنی اسے مرتب کرنے کے بعد محفوظ نہیں کیا جاتا ہے)۔ عام طور پر کسی بھی پری پروسیسرز (مشروط طور پر) یا کمپائلر کو ہدایات کے لیے استعمال کیا جاتا ہے۔
  • کلاس - تشریح کو تالیف کے بعد محفوظ کیا جاتا ہے، لیکن JVM کے ذریعہ نظر انداز کیا جاتا ہے (یعنی رن ٹائم کے وقت استعمال نہیں کیا جا سکتا)۔ عام طور پر کسی بھی فریق ثالث کی خدمات کے لیے استعمال کیا جاتا ہے جو آپ کے کوڈ کو بطور پلگ ان ایپلیکیشن لوڈ کرتی ہے۔
  • RUNTIME ایک تشریح ہے جو تالیف کے بعد محفوظ کی جاتی ہے اور JVM کے ذریعے لوڈ کی جاتی ہے (یعنی خود پروگرام کے عمل کے دوران استعمال کیا جا سکتا ہے)۔ کوڈ میں نشانات کے طور پر استعمال کیا جاتا ہے جو پروگرام کے عمل کو براہ راست متاثر کرتے ہیں (ایک مثال اس مضمون میں زیر بحث آئے گی)

جس چیز کی اوپر اشارہ کیا گیا ہے۔

اس تفصیل کو تقریباً لفظی طور پر لیا جانا چاہیے، کیونکہ... جاوا میں، تشریحات کو کسی بھی چیز (فیلڈز، کلاسز، فنکشنز، وغیرہ) پر بیان کیا جا سکتا ہے اور ہر تشریح کے لیے اس بات کی نشاندہی کی جاتی ہے کہ اس کی بالکل کیا وضاحت کی جا سکتی ہے۔ یہاں اب کوئی "ایک چیز" کا اصول نہیں ہے؛ ذیل میں درج ہر چیز کے اوپر ایک تشریح بیان کی جا سکتی ہے، یا آپ ElementType کلاس کے صرف ضروری عناصر کو منتخب کر سکتے ہیں :
  • ANNOTATION_TYPE - ایک اور تشریح
  • کنسٹرکٹر - کلاس کنسٹرکٹر
  • FIELD - کلاس فیلڈ
  • LOCAL_VARIABLE - مقامی متغیر
  • طریقہ - کلاس کا طریقہ
  • PACKAGE - پیکیج پیکج کی تفصیل
  • پیرامیٹر - طریقہ پیرامیٹر عوامی باطل ہیلو(@Annontation String param){}
  • TYPE - کلاس کے اوپر اشارہ کیا گیا ہے۔
مجموعی طور پر، Java SE 1.8 کے مطابق، معیاری زبان کی لائبریری ہمیں 10 تشریحات فراہم کرتی ہے۔ اس مضمون میں ہم ان میں سے سب سے عام کو دیکھیں گے (جو ان سب میں دلچسپی رکھتے ہیں؟ Javadoc میں خوش آمدید ):

@Override

برقرار رکھنا: SOURCE; ہدف: طریقہ۔ یہ تشریح ظاہر کرتی ہے کہ جس طریقہ پر یہ لکھا گیا ہے وہ پیرنٹ کلاس سے وراثت میں ملا ہے۔ پہلی تشریح جو ہر نوسکھئیے جاوا پروگرامر کے پاس آئی ڈی ای استعمال کرتے وقت آتی ہے جو ان @Override کو مسلسل دھکیلتا ہے۔ اکثر، یوٹیوب کے اساتذہ یا تو تجویز کرتے ہیں: "اسے مٹا دیں تاکہ یہ مداخلت نہ کرے" یا: "یہ سوچے بغیر چھوڑ دیں کہ یہ وہاں کیوں ہے۔" درحقیقت، تشریح مفید سے کہیں زیادہ ہے: یہ نہ صرف آپ کو یہ سمجھنے کی اجازت دیتا ہے کہ اس کلاس میں پہلی بار کون سے طریقے بیان کیے گئے تھے، اور کون سے والدین کے پاس پہلے سے موجود ہیں (جو بلاشبہ آپ کے کوڈ کی پڑھنے کی اہلیت کو بڑھاتا ہے)، بلکہ یہ تشریح بھی۔ ایک "سیلف چیک" کے طور پر کام کرتا ہے کہ اوورلوڈ فنکشن کی وضاحت کرتے وقت آپ سے غلطی نہیں ہوئی تھی۔

@فرسودہ

برقرار رکھنا: رن ٹائم؛ ہدف: CONSTRUCTOR، FIELD، LOCAL_VARIABLE، METHOD، PACKAGE، PARAMETER، TYPE۔ یہ تشریح ان طریقوں، کلاسوں یا متغیرات کی نشاندہی کرتی ہے جو "متروک" ہیں اور پروڈکٹ کے مستقبل کے ورژن میں ہٹائے جا سکتے ہیں۔ اس تشریح کا سامنا عام طور پر ان لوگوں کو ہوتا ہے جو کسی بھی APIs، یا اسی معیاری جاوا لائبریری کی دستاویزات کو پڑھتے ہیں۔ بعض اوقات اس تشریح کو نظر انداز کر دیا جاتا ہے کیونکہ... یہ کسی قسم کی غلطیوں کا سبب نہیں بنتا اور اصولی طور پر خود زندگی میں زیادہ مداخلت نہیں کرتا۔ تاہم، اس تشریح میں جو اہم پیغام ہے وہ یہ ہے کہ "ہم اس فعالیت کو نافذ کرنے کے لیے ایک زیادہ آسان طریقہ لے کر آئے ہیں، اسے استعمال کریں، پرانا استعمال نہ کریں" - ٹھیک ہے، ورنہ - "ہم نے فنکشن کا نام تبدیل کر دیا، لیکن یہ ایسا ہے، ہم نے اسے وراثت کے لیے چھوڑ دیا..." (جو عام طور پر برا بھی نہیں ہے)۔ مختصراً، اگر آپ @ Deprecated دیکھتے ہیں، تو بہتر ہے کہ اسے استعمال نہ کرنے کی کوشش کریں جب تک کہ یہ بالکل ضروری نہ ہو، اور یہ سمجھنے کے لیے دستاویزات کو دوبارہ پڑھنے کے قابل ہو سکتا ہے کہ فرسودہ عنصر کے ذریعے انجام پانے والے کام کو اب کیسے نافذ کیا جاتا ہے۔ مثال کے طور پر، نئی Date().getYear() استعمال کرنے کے بجائے Calendar.getInstance().get(Calendar.YEAR) استعمال کرنے کی سفارش کی جاتی ہے ۔

@Suppress وارننگز

برقرار رکھنا: SOURCE; ہدف: TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE یہ تشریح کمپائلر انتباہات کے آؤٹ پٹ کو غیر فعال کرتی ہے جو اس عنصر سے متعلق ہے جس پر اس کی وضاحت کی گئی ہے۔ کیا SOURCE تشریح فیلڈز، طریقوں، کلاسوں کے اوپر اشارہ کیا گیا ہے۔

@ برقرار رکھنا

برقرار رکھنا: RUNTIME؛ ہدف: ANNOTATION_TYPE؛ یہ تشریح اس تشریح کی "اسٹوریج کی قسم" کو بتاتی ہے جس کے اوپر اس کی وضاحت کی گئی ہے۔ ہاں، یہ تشریح اپنے لیے بھی استعمال ہوتی ہے... جادو اور بس۔

@ٹارگٹ

برقرار رکھنا: RUNTIME؛ ہدف: ANNOTATION_TYPE؛ یہ تشریح اس چیز کی قسم کی وضاحت کرتی ہے جس پر ہماری تخلیق کردہ تشریح کی نشاندہی کی جاسکتی ہے۔ جی ہاں، اور یہ آپ کے لیے بھی استعمال ہوتا ہے، اس کی عادت ڈالیں... میرے خیال میں یہ وہ جگہ ہے جہاں ہم جاوا لائبریری کے معیاری تشریحات کا اپنا تعارف مکمل کر سکتے ہیں، کیونکہ باقی بہت کم استعمال کیے جاتے ہیں اور، اگرچہ ان کے اپنے فوائد ہیں، ہر ایک کو ان سے نمٹنے کی ضرورت نہیں ہے اور یہ مکمل طور پر غیر ضروری ہے۔ اگر آپ چاہتے ہیں کہ میں معیاری لائبریری سے کسی مخصوص تشریح کے بارے میں بات کروں (یا، شاید، @NotNull اور @Nullable جیسی تشریحات، جو STL میں شامل نہیں ہیں)، تبصرے میں لکھیں - یا تو مہربان صارف آپ کو وہاں جواب دیں گے، یا جب میں اسے دیکھوں گا. اگر بہت سے لوگ کسی قسم کی تشریح طلب کریں تو میں اسے بھی مضمون میں شامل کروں گا۔

RUNTIME تشریحات کا عملی اطلاق

دراصل، مجھے لگتا ہے کہ یہ کافی نظریاتی بات ہے: آئیے بوٹ کی مثال کو استعمال کرتے ہوئے مشق کرنے کے لیے آگے بڑھیں۔ فرض کریں کہ آپ کسی سوشل نیٹ ورک کے لیے بوٹ لکھنا چاہتے ہیں۔ تمام بڑے نیٹ ورکس، جیسے کہ VK، Facebook، Discord، کے اپنے APIs ہیں جو آپ کو بوٹ لکھنے کی اجازت دیتے ہیں۔ انہی نیٹ ورکس کے لیے، APIs کے ساتھ کام کرنے کے لیے پہلے سے ہی تحریری لائبریریاں موجود ہیں، بشمول Java میں۔ لہذا، ہم کسی بھی API یا لائبریری کے کام میں دلچسپی نہیں لیں گے۔ اس مثال میں ہمیں صرف یہ جاننے کی ضرورت ہے کہ ہمارا بوٹ اس چیٹ پر بھیجے گئے پیغامات کا جواب دے سکتا ہے جس میں ہمارا بوٹ واقعتاً موجود ہے۔ یعنی، ہم کہتے ہیں کہ ہمارے پاس ایک فنکشن کے ساتھ میسج لسٹنر کلاس ہے:
public class MessageListener
{
    public void onMessageReceived(MessageReceivedEvent event)
    {
    }
}
یہ موصول ہونے والے پیغام پر کارروائی کے لیے ذمہ دار ہے۔ MessageReceivedEvent کلاس سے ہمیں صرف موصول ہونے والے پیغام کی تار کی ضرورت ہے (مثال کے طور پر، "ہیلو" یا "بوٹ، ہیلو")۔ یہ قابل غور ہے: مختلف لائبریریوں میں ان کلاسوں کو مختلف طریقے سے کہا جاتا ہے۔ میں نے ڈسکارڈ کے لیے لائبریری کا استعمال کیا۔ اور اس لیے ہم بوٹ کو "بوٹ" سے شروع ہونے والے کچھ حکموں پر ردعمل کا اظہار کرنا چاہتے ہیں (کوما کے ساتھ یا اس کے بغیر - خود فیصلہ کریں: اس سبق کی خاطر، ہم یہ فرض کریں گے کہ وہاں کوما نہیں ہونا چاہیے)۔ یعنی ہمارا فنکشن کچھ اس طرح سے شروع ہوگا:
public void onMessageReceived(MessageReceivedEvent event)
{
    //Убираем чувствительность к регистру (БоТ, бОт и т.д.)
    String message = event.getMessage().toLowerCase();
    if (message.startsWith("бот"))
    {

    }
}
اور اب ہمارے پاس اس یا اس کمانڈ کو نافذ کرنے کے لیے بہت سے اختیارات ہیں۔ بلاشبہ، پہلے آپ کو کمانڈ کو اس کے دلائل سے الگ کرنا ہوگا، یعنی اسے ایک صف میں تقسیم کرنا ہوگا۔
public void onMessageReceived(MessageReceivedEvent event)
{
    //Убираем чувствительность к регистру (БоТ, бОт и т.д.)
    String message = event.getMessage().toLowerCase();
    if (message.startsWith("бот"))
    {
        try
        {
            //получим массив {"Бот", "(команду)", "аргумент1", "аргумент2",... "аргументN"};
            String[] args = message.split(" ");
            //Для удобства уберем "бот" и отделим команду от аргументов
            String command = args[1];
            String[] nArgs = Arrays.copyOfRange(args, 2, args.length);
            //Получor command = "(команда)"; nArgs = {"аргумент1", "аргумент2",..."аргументN"};
            //Данный массив может быть пустым
        }
        catch (ArrayIndexOutOfBoundsException e)
        {
            //Вывод списка команд or Howого-либо messages
            //В случае если просто написать "Бот"
        }
    }
}
کوڈ کے اس ٹکڑے سے بچنے کا کوئی طریقہ نہیں ہے، کیونکہ کمانڈ کو دلائل سے الگ کرنا ہمیشہ ضروری ہوتا ہے۔ لیکن پھر ہمارے پاس ایک انتخاب ہے:
  • کریں if(command.equalsIngnoreCase("..."))
  • سوئچ کریں (کمانڈ)
  • پروسیسنگ کا کوئی دوسرا طریقہ کریں...
  • یا تشریحات کی مدد کا سہارا لیں۔
اور اب ہم آخر کار تشریحات کو استعمال کرنے کے عملی حصے تک پہنچ گئے ہیں۔ آئیے اپنے کام کے لیے تشریحی کوڈ کو دیکھتے ہیں (یقیناً یہ مختلف ہو سکتا ہے)۔
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//Указывает, что наша Аннотация может быть использована
//Во время выполнения через Reflection (нам How раз это нужно).
@Retention(RetentionPolicy.RUNTIME)

//Указывает, что целью нашей Аннотации является метод
//Не класс, не переменная, не поле, а именно метод.
@Target(ElementType.METHOD)
public @interface Command //Описание. Заметим, что перед interface стоит @;
{
    //Команда за которую будет отвечать функция (например "привет");
    String name();

     //Аргументы команды, использоваться будут для вывода списка команд
    String args();

     //Минимальное количество аргументов, сразу присвоor 0 (логично)
    int minArgs() default 0;

    //Описание, тоже для списка
    String desc();

     //Максимальное число аргументов. В целом не обязательно, но тоже можно использовать
    int maxArgs() default Integer.MAX_VALUE;

     //Показывать ли команду в списке (вовсе необязательная строка, но мало ли, пригодится!)
    boolean showInHelp() default true;

    //Какие команды будут считаться эквивалентными нашей
    //(Например для "привет", это может быть "Здаров", "Прив" и т.д.)
    //Под каждый случай заводить функцию - не рационально
    String[] aliases();

}
اہم! ہر پیرامیٹر کو ایک فنکشن کے طور پر بیان کیا گیا ہے (قوسین کے ساتھ)۔ صرف primitives، String ، Enum کو پیرامیٹرز کے طور پر استعمال کیا جا سکتا ہے ۔ آپ List<String> args() نہیں لکھ سکتے ؛ --.غلطی اب جب کہ ہم نے تشریح بیان کر دی ہے، آئیے ایک کلاس بناتے ہیں، اسے CommandListener کہتے ہیں ۔
public class CommandListener
{
    @Command(name = "привет",
            args = "",
            desc = "Будь культурным, поздоровайся",
            showInHelp = false,
            aliases = {"здаров"})
    public void hello(String[] args)
    {
        //Какой-то функционал, на Ваше усмотрение.
    }

    @Command(name = "пока",
            args = "",
            desc = "",
            aliases = {"удачи"})
    public void bye(String[] args)
    {
         // Функционал
    }

    @Command(name = "помощь",
            args = "",
            desc = "Выводит список команд",
            aliases = {"help", "команды"})
    public void help(String[] args)
    {
        StringBuilder sb = new StringBuilder("Список команд: \n");
        for (Method m : this.getClass().getDeclaredMethods())
        {
            if (m.isAnnotationPresent(Command.class))
            {
                Command com = m.getAnnotation(Command.class);
                if (com.showInHelp()) //Если нужно показывать команду в списке.
                {
                    sb.append("Бот, ")
                       .append(com.name()).append(" ")
                       .append(com.args()).append(" - ")
                       .append(com.desc()).append("\n");
                }
            }
        }
        //Отправка sb.toString();

    }
}
یہ ایک چھوٹی سی تکلیف کو نوٹ کرنے کے قابل ہے: t.c. اب ہم آفاقیت کے لیے لڑ رہے ہیں، تمام فنکشنز میں رسمی پیرامیٹرز کی ایک ہی فہرست ہونی چاہیے، اس لیے اگر کمانڈ میں کوئی دلیل نہیں ہے، فنکشن میں String[] args پیرامیٹر ہونا چاہیے ۔ اب ہم نے 3 کمانڈز بیان کیے ہیں: ہیلو، بائے، مدد۔ اب آئیے اس کے ساتھ کچھ کرنے کے لیے اپنے MessageListener میں ترمیم کریں۔ سہولت اور کام کی رفتار کے لیے، ہم فوری طور پر اپنے کمانڈز کو HashMap میں محفوظ کریں گے :
public class MessageListner
{
    //Map который хранит How ключ команду
    //А How meaning функцию которая будет обрабатывать команду
    private static final Map<String, Method> COMMANDS = new HashMap<>();

    //Объект класса с командами (по сути нужен нам для рефлексии)
    private static final CommandListener LISTENER = new CommandListener();

    static
    {
       //Берем список всех методов в классе CommandListener
        for (Method m : LISTENER.getClass().getDeclaredMethods())
        {
            //Смотрим, есть ли у метода нужная нам Аннотация @Command
            if (m.isAnnotationPresent(Command.class))
            {
                //Берем an object нашей Аннотации
                Command cmd = m.getAnnotation(Command.class);
                //Кладем в качестве ключа нашей карты параметр name()
                //Определенный у нашей аннотации,
                //m — переменная, хранящая наш метод
                COMMANDS.put(cmd.name(), m);

                //Также заносим каждый элемент aliases
               //Как ключ указывающий на тот же самый метод.
                for (String s : cmd.aliases())
                {
                    COMMANDS.put(s, m);
                }
            }
        }
    }

    public void onMessageReceived(MessageReceivedEvent event)
    {

        String message = event.getMessage().toLowerCase();
        if (message.startsWith("бот"))
        {
            try
            {
                String[] args = message.split(" ");
                String command = args[1];
                String[] nArgs = Arrays.copyOfRange(args, 2, args.length);
                Method m = COMMANDS.get(command);
                if (m == null)
                {
                    //(вывод помощи)
                    return;
                }
                Command com = m.getAnnotation(Command.class);
                if (nArgs.length < com.minArgs())
                {
                    //что-то если аргументов меньше чем нужно
                }
                else if (nArgs.length > com.maxArgs())
                {
                    //что-то если аргументов больше чем нужно
                }
                //Через рефлексию вызываем нашу функцию-обработчик
                //Именно потому что мы всегда передаем nArgs у функции должен быть параметр
                //String[] args — иначе она просто не будет найдена;
                m.invoke(LISTENER, nArgs);
            }
            catch (ArrayIndexOutOfBoundsException e)
            {
                //Вывод списка команд or Howого-либо messages
                //В случае если просто написать "Бот"
            }
        }
    }
}
ہماری ٹیموں کو کام کرنے کے لیے بس اتنا ہی درکار ہے۔ اب نئی کمانڈ شامل کرنا کوئی نئی بات نہیں ہے، کوئی نئی صورت نہیں، جس میں دلائل کی تعداد کو دوبارہ گننا پڑے گا، اور مدد کو بھی دوبارہ لکھنا پڑے گا، اس میں نئی ​​لائنیں شامل کر کے۔ اب، کمانڈ شامل کرنے کے لیے، ہمیں CommandListener کلاس میں @Command تشریح کے ساتھ ایک نیا فنکشن شامل کرنے کی ضرورت ہے اور بس - کمانڈ کو شامل کیا جاتا ہے، معاملات کو مدنظر رکھا جاتا ہے، مدد خود بخود شامل ہوجاتی ہے۔ یہ بالکل ناقابل تردید ہے کہ یہ مسئلہ بہت سے دوسرے طریقوں سے حل کیا جاسکتا ہے۔ ہاں، ہر وہ چیز جو تشریحات/مظاہر کی مدد سے کی جا سکتی ہے ان کے بغیر بھی کی جا سکتی ہے، سوال صرف سہولت، بہترینیت اور کوڈ کے سائز کا ہے، بلاشبہ، جہاں بھی معمولی اشارہ ہو وہاں ایک تشریح کو چسپاں کرنا کہ اسے استعمال کرنا ممکن ہو گا۔ یہ سب سے زیادہ عقلی آپشن بھی نہیں ہے، ہر چیز میں آپ کو یہ جاننے کی ضرورت ہے کہ کب روکنا ہے =)۔ لیکن جب APIs، لائبریریوں یا پروگراموں کو لکھتے ہیں جس میں ایک ہی قسم کا (لیکن بالکل ایک جیسا نہیں) کوڈ کو دہرانا ممکن ہے، تو بلاشبہ تشریحات بہترین حل ہیں۔
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION