পিএইচপি-র বৈশিষ্ট্য - কোনও বাস্তব বিশ্বের উদাহরণ / সেরা অনুশীলন? [বন্ধ]


148

বৈশিষ্ট্যগুলি পিএইচপি 5.4-র জন্য সর্বাধিক সংযোজন হয়েছে। আমি সিনট্যাক্সটি জানি এবং বৈশিষ্ট্যের পিছনে ধারণাটি বুঝতে পারি, যেমন লগিং, সুরক্ষা, ক্যাশিং ইত্যাদি সাধারণ জিনিসগুলির জন্য অনুভূমিক কোড পুনরায় ব্যবহার re

তবে আমি কীভাবে আমার প্রকল্পগুলিতে বৈশিষ্ট্য ব্যবহার করব তা এখনও জানি না।

ইতিমধ্যে বৈশিষ্টগুলি ব্যবহার করে এমন কোনও ওপেন সোর্স প্রকল্প রয়েছে? বৈশিষ্ট্যগুলি ব্যবহার করে কীভাবে আর্কিটেকচারের কাঠামো তৈরি করা যায় সে সম্পর্কে কোনও ভাল নিবন্ধ / পঠন সামগ্রী?


8
এখানে আমার মতামত: আমি এই বিষয়ে লিখেছি সেই বিষয়ে একটি ব্লগ পোস্ট । টিএল; ডিআর: মূলত, আমি আশঙ্কা করি যে তারা শক্তিশালী এবং তাদের ভাল ব্যবহারের জন্য ব্যবহার করা যেতে পারে, তবে আমরা দেখতে পাব যে বেশিরভাগ ব্যবহার সম্পূর্ণ বিরোধী নিদর্শন হতে চলেছে এবং তারা সমাধানের চেয়ে অনেক বেশি ব্যথার কারণ হয়ে
উঠবে

1
কটাক্ষপাত Scala মান গ্রন্থাগার এবং আপনার বৈশিষ্ট্যগুলো অনেক দরকারী উদাহরণ খুঁজে বের করতে হবে।
দিমিত্রি

উত্তর:


89

আমার ব্যক্তিগত মতামতটি হ'ল ক্লিন কোড লেখার সময় বৈশিষ্টগুলির জন্য আসলে খুব কম প্রয়োগ রয়েছে।

ক্লাসে কোড হ্যাক করার জন্য বৈশিষ্ট্যগুলি ব্যবহার না করে কনস্ট্রাক্টরের মাধ্যমে বা সেটটারগুলির মাধ্যমে নির্ভরতাগুলিতে পাস করা ভাল:

class ClassName {
    protected $logger;

    public function __construct(LoggerInterface $logger) {
        $this->logger = $logger;
    }
    // or
    public function setLogger(LoggerInterface $logger) {
        $this->logger = $logger;
    }
}

বৈশিষ্ট্যগুলি ব্যবহার করার চেয়ে আমি কেন এটি আরও ভাল খুঁজে পাই তার মূল কারণ হ'ল আপনার কোডটি কোনও বৈশিষ্ট্যের মধ্যে হার্ড কাপলিং সরিয়ে আরও বেশি নমনীয়। উদাহরণস্বরূপ আপনি এখন অন্য একটি লগার ক্লাসটি সহজভাবে পাস করতে পারেন। এটি আপনার কোডটিকে পুনরায় ব্যবহারযোগ্য এবং পরীক্ষামূলক করে তোলে।


4
বৈশিষ্ট্য ব্যবহার করে, আপনি ঠিক অন্য লগার শ্রেণিটিও ব্যবহার করতে পারেন? কেবল বৈশিষ্ট্য সম্পাদনা করুন, এবং বৈশিষ্ট্য ব্যবহার করে এমন সমস্ত শ্রেণি আপডেট হয়। আমি ভুল হলে আমাকে সংশোধন করুন
রিক্রিস্টিটি

14
@ ক্রিক্রিস্টি অবশ্যই, আপনি এটি করতে পারতেন। তবে আপনাকে বৈশিষ্ট্যের উত্স কোডটি সম্পাদনা করতে হবে। সুতরাং আপনি এটি ব্যবহার করে প্রতিটি শ্রেণীর জন্য এটি পরিবর্তন করবেন, কেবল যে নির্দিষ্ট শ্রেণীর জন্য আপনি আলাদা লগার চান তা নয়। এবং যদি আপনি একই শ্রেণিটি ব্যবহার করতে চান তবে দুটি পৃথক লগার দিয়ে থাকেন? বা আপনি যদি পরীক্ষার সময় মক-লগার পাস করতে চান? আপনি পারবেন না, আপনি যদি বৈশিষ্ট্য ব্যবহার করেন তবে আপনি পারেন, যদি আপনি নির্ভরতা ইঞ্জেকশন ব্যবহার করেন।
নিকিসি

2
আমি আপনার বক্তব্যটি দেখতে পাচ্ছি, I´m এছাড়াও বিবেচনা করছে যে বৈশিষ্ট্যগুলি এটির জন্য মূল্যবান কিনা। আমি বলতে চাইছি সিমফোনি 2 এর মতো আধুনিক ফ্রেমওয়ার্কগুলিতে আপনার পুরো জায়গা জুড়ে নির্ভরতা ইনজেকশন রয়েছে যা বেশিরভাগ ক্ষেত্রেই বৈশিষ্ট্যের চেয়ে বেশি বলে মনে হয় super এই মুহুর্তে আমি বৈশিষ্ট্যগুলি আরও বেশি হিসাবে দেখতে পাই না "সংকলক সহকারী অনুলিপি এবং পেস্ট"। ;)
সর্বাধিক

11
এই মুহুর্তে আমি বৈশিষ্ট্যগুলি আরও বেশি হিসাবে দেখতে পাই না "সংকলক সহকারী অনুলিপি এবং পেস্ট"। ;) : @ ম্যাক্স: বৈশিষ্ট্যগুলি ঠিক এটির জন্য ডিজাইন করা হয়েছিল, তাই এটি সম্পূর্ণ সঠিক। এটি এটিকে আরও "রক্ষণাবেক্ষণযোগ্য" করে তোলে, যেহেতু কেবলমাত্র একটি সংজ্ঞা আছে, তবে এটি মূলত কেবল সি & পি ...
ইরকমেক্সেল

29
নিকিস এর পয়েন্টটি অনুপস্থিত: একটি বৈশিষ্ট্য ব্যবহার করে নির্ভরতা ইনজেকশন ব্যবহার করা বাধা দেয় না। এই ক্ষেত্রে, একটি বৈশিষ্ট্য কেবলমাত্র প্রতিটি ক্লাসে যে লগিং প্রয়োগ করে সেটলোগার () পদ্ধতি এবং $ লগার সম্পত্তি তৈরির নকল করতে দেয় না। বৈশিষ্ট্য তাদের সরবরাহ করবে। সেটলগার () উদাহরণ হিসাবে যেমনটি লগারআইনটারফেসে ইঙ্গিতটি টাইপ করবে, যাতে যে কোনও ধরণের লগার প্রবেশ করতে পারে This )।
ইথান

205

আমি অনুমান করি যে গ্রহণযোগ্য ভাল / সেরা অনুশীলনগুলি শিখতে এখন এমন কিছু ভাষা রয়েছে যা কিছু সময়ের জন্য ট্রেইটস রয়েছে into ট্রেইট সম্পর্কে আমার বর্তমান মতামতটি হ'ল আপনার কেবলমাত্র কোডের জন্য সেগুলি ব্যবহার করা উচিত যা আপনাকে একই কার্যকারিতা ভাগ করে নেওয়ার জন্য অন্যান্য শ্রেণিতে নকল করতে হবে।

লগার বৈশিষ্ট্যের উদাহরণ:

interface Logger
{
    public function log($message, $level);    
}

class DemoLogger implements Logger
{
    public function log($message, $level)
    {
        echo "Logged message: $message with level $level", PHP_EOL; 
    }
}

trait Loggable // implements Logger
{
    protected $logger;
    public function setLogger(Logger $logger)
    {
        $this->logger = $logger;
    }
    public function log($message, $level)
    {
        $this->logger->log($message, $level);
    }
}

class Foo implements Logger
{
    use Loggable;
}

এবং তারপরে আপনি ( ডেমো ) করুন

$foo = new Foo;
$foo->setLogger(new DemoLogger);
$foo->log('It works', 1);

আমি অনুমান করি যে বৈশিষ্ট্যগুলি ব্যবহার করার সময় এটি বিবেচনা করার জন্য গুরুত্বপূর্ণ বিষয়টি হ'ল তারা আসলে কোডের টুকরো যা ক্লাসে অনুলিপি করে get উদাহরণস্বরূপ, আপনি যখন পদ্ধতিগুলির দৃশ্যমানতা পরিবর্তন করার চেষ্টা করেন এটি সহজেই সংঘাত সৃষ্টি করতে পারে

trait T {
    protected function foo() {}
}
class A { 
    public function foo() {}
}
class B extends A
{
    use T;
}

উপরেরটির ফলে একটি ত্রুটি হবে ( ডেমো )। তেমনিভাবে, ব্যবহার শ্রেণিতে ইতিমধ্যে ঘোষিত বৈশিষ্ট্যগুলিতে ঘোষিত কোনও পদ্ধতি ক্লাসে অনুলিপি করা হবে না, যেমন

trait T {
    public function foo() {
    return 1;
}
}
class A { 
    use T;
    public function foo() {
    return 2;
}
}

$a = new A;
echo $a->foo();

2 ( ডেমো ) মুদ্রণ করবে । এগুলি আপনি এড়াতে চাইবেন কারণ তারা ত্রুটিগুলি খুঁজে পাওয়া শক্ত করে। আপনি এমন বৈশিষ্ট্যগুলিতে এমন জিনিসগুলি স্থাপন করা এড়াতে চাইবেন যা এটি ব্যবহার করে এমন শ্রেণীর বৈশিষ্ট্য বা পদ্ধতিগুলিতে

class A
{
    use T;
    protected $prop = 1;
    protected function getProp() {
        return $this->prop;
    }
}

trait T
{
    public function foo()
    {
        return $this->getProp();
    }
}

$a = new A;
echo $a->foo();

কাজ করে ( ডেমো ) তবে এখন বৈশিষ্টটি নিবিড়ভাবে A এর সাথে মিলিত হয়েছে এবং অনুভূমিক পুনরায় ব্যবহারের পুরো ধারণাটি হারিয়ে গেছে।

আপনি যখন ইন্টারফেস বিভাজন নীতিটি অনুসরণ করেন তখন আপনার অনেকগুলি ছোট ছোট ক্লাস এবং ইন্টারফেস থাকে। এটি বৈশিষ্ট্যগুলি আপনার উল্লিখিত জিনিসগুলির জন্য আদর্শ প্রার্থী করে তোলে, যেমন উদ্বিগ্ন উদ্বেগ , তবে অবজেক্টগুলি রচনা না করা (কাঠামোগত অর্থে)। উপরে আমাদের লগার উদাহরণে, বৈশিষ্ট্যটি সম্পূর্ণ বিচ্ছিন্ন। কংক্রিট ক্লাসের উপর এর কোনও নির্ভরতা নেই।

একই ফলস্বরূপ শ্রেণি অর্জনের জন্য আমরা সমষ্টি / রচনা (যেমন এই পৃষ্ঠায় অন্য কোথাও দেখানো হয়েছে) ব্যবহার করতে পারি, তবে সমষ্টি / রচনা ব্যবহারের অপূর্ণতা হ'ল আমাদের অবশ্যই প্রতিটি এবং প্রতিটি শ্রেণীর মধ্যে প্রক্সি / প্রতিনিধি পদ্ধতি যুক্ত করতে হবে লগ করতে সক্ষম। বৈশিষ্ট্যগুলি আমাকে বয়লারপ্লেটটিকে এক জায়গায় রাখার অনুমতি দিয়ে এবং যেখানে প্রয়োজন সেখানে বেছে বেছে এটি প্রয়োগ করে সুন্দরভাবে সমাধান করে।

দ্রষ্টব্য: প্রদত্ত বৈশিষ্ট্যগুলি পিএইচপি-তে একটি নতুন ধারণা, উপরে প্রকাশিত সমস্ত মতামত পরিবর্তিত হতে পারে। আমি নিজেই ধারণাটি মূল্যায়নের জন্য খুব বেশি সময় পাইনি। তবে আমি আশা করি আপনার সম্পর্কে কিছু ভাবার জন্য এটি যথেষ্ট ভাল।


41
একটি আকর্ষণীয় ব্যবহারের ক্ষেত্রে এটি পরিচালনা করে: একটি ইন্টারফেস ব্যবহার করুন যা চুক্তিটিকে সংজ্ঞায়িত করে, সেই চুক্তিটি সন্তুষ্ট করতে বৈশিষ্ট্যটি ব্যবহার করুন। ভাল একটা.
সর্বোচ্চ

13
আমি এই জাতীয় সত্য প্রোগ্রামার পছন্দ করি, যারা প্রত্যেকের জন্য সংক্ষিপ্ত ডেস্ক সহ বাস্তব কাজের উদাহরণ প্রস্তাব করে। থেক্স
আর্থার কুশমান

1
এর পরিবর্তে যদি কেউ একটি বিমূর্ত ক্লাস ব্যবহার করে? ইন্টারফেস এবং বৈশিষ্ট্য প্রতিস্থাপন, একটি বিমূর্ত শ্রেণি তৈরি করতে পারেন। এছাড়াও যদি ইন্টারফেসটি অ্যাপ্লিকেশনটির জন্য প্রয়োজনীয় হয় তবে বিমূর্ত শ্রেণি ইন্টারফেসটি বাস্তবায়ন করতে পারে এবং বৈশিষ্ট্যের মতো পদ্ধতিগুলিও সংজ্ঞায়িত করতে পারে। তাহলে কেন আপনি ব্যাখ্যা করতে পারেন কেন আমাদের এখনও বৈশিষ্ট্যের প্রয়োজন?
সুমনচালকি

12
@ সুমনচালকি বিমূর্ত শ্রেণি উত্তরাধিকারের নিয়মগুলি অনুসরণ করে। আপনার যদি এমন ক্লাসের প্রয়োজন হয় যা লগেবল এবং ক্যাশেবল কার্যকর করে? আপনাকে AbstractLogger প্রসারিত করতে ক্লাসের প্রয়োজন হবে যা তার পরে AbstractCache প্রসারিত করতে হবে। তবে এর মানে হল যে সমস্ত লগগেবলগুলি হ'ল ক্যাচ। এটি আপনি চান না একটি সংযোগ। এটি আপনার উত্তরাধিকারের গ্রাফটিকে পুনঃব্যবহার এবং মেসেজ সীমাবদ্ধ করে।
গর্ডন

1
আমার মনে হয় ডেমো লিঙ্কগুলি মারা গেছে
Pmpr

19

:) কোনও কিছু দিয়ে কী করা উচিত তা নিয়ে তাত্ত্বিক ধারণা এবং বিতর্ক করতে আমি পছন্দ করি না। এই ক্ষেত্রে বৈশিষ্ট্য। আমি কীগুলির জন্য আমার বৈশিষ্ট্যগুলি কার্যকর বলে মনে করব এবং আপনি তা থেকে শিখতে পারেন, বা এড়িয়ে যেতে পারেন।

বৈশিষ্ট্য - কৌশল প্রয়োগের জন্য তারা দুর্দান্ত । সংক্ষেপে কৌশলগত নকশার নিদর্শনগুলি কার্যকর যখন আপনি একই ডেটা হ্যান্ডেল করতে চান (ফিল্টার করা, সাজানো ইত্যাদি) আলাদাভাবে।

উদাহরণস্বরূপ, আপনার কাছে এমন কিছু পণ্যগুলির তালিকা রয়েছে যা আপনি কিছু মানদণ্ডের (ব্র্যান্ড, চশমা, যাই হোক না কেন), বা বিভিন্ন উপায়ে (দাম, লেবেল, যাই হোক না কেন) দ্বারা বাছাই করে ফিল্টার করতে চান। আপনি একটি বাছাই করা বৈশিষ্ট্য তৈরি করতে পারেন যা বিভিন্ন বাছাই করার ধরণের (সংখ্যা, স্ট্রিং, তারিখ, ইত্যাদি) এর জন্য বিভিন্ন ফাংশন ধারণ করে। তারপরে আপনি এই বৈশিষ্ট্যটি কেবল আপনার পণ্য শ্রেণিতেই ব্যবহার করতে পারবেন না (উদাহরণস্বরূপ যেমনটি দেওয়া হয়েছে), কিন্তু অন্যান্য শ্রেণিতেও একই ধরণের কৌশল প্রয়োজন (কিছু উপায়ে সংখ্যাসূচক বাছাই করা ইত্যাদি)।

এটি চেষ্টা করুন:

<?php
trait SortStrategy {
    private $sort_field = null;
    private function string_asc($item1, $item2) {
        return strnatcmp($item1[$this->sort_field], $item2[$this->sort_field]);
    }
    private function string_desc($item1, $item2) {
        return strnatcmp($item2[$this->sort_field], $item1[$this->sort_field]);
    }
    private function num_asc($item1, $item2) {
        if ($item1[$this->sort_field] == $item2[$this->sort_field]) return 0;
        return ($item1[$this->sort_field] < $item2[$this->sort_field] ? -1 : 1 );
    }
    private function num_desc($item1, $item2) {
        if ($item1[$this->sort_field] == $item2[$this->sort_field]) return 0;
        return ($item1[$this->sort_field] > $item2[$this->sort_field] ? -1 : 1 );
    }
    private function date_asc($item1, $item2) {
        $date1 = intval(str_replace('-', '', $item1[$this->sort_field]));
        $date2 = intval(str_replace('-', '', $item2[$this->sort_field]));
        if ($date1 == $date2) return 0;
        return ($date1 < $date2 ? -1 : 1 );
    }
    private function date_desc($item1, $item2) {
        $date1 = intval(str_replace('-', '', $item1[$this->sort_field]));
        $date2 = intval(str_replace('-', '', $item2[$this->sort_field]));
        if ($date1 == $date2) return 0;
        return ($date1 > $date2 ? -1 : 1 );
    }
}

class Product {
    public $data = array();

    use SortStrategy;

    public function get() {
        // do something to get the data, for this ex. I just included an array
        $this->data = array(
            101222 => array('label' => 'Awesome product', 'price' => 10.50, 'date_added' => '2012-02-01'),
            101232 => array('label' => 'Not so awesome product', 'price' => 5.20, 'date_added' => '2012-03-20'),
            101241 => array('label' => 'Pretty neat product', 'price' => 9.65, 'date_added' => '2012-04-15'),
            101256 => array('label' => 'Freakishly cool product', 'price' => 12.55, 'date_added' => '2012-01-11'),
            101219 => array('label' => 'Meh product', 'price' => 3.69, 'date_added' => '2012-06-11'),
        );
    }

    public function sort_by($by = 'price', $type = 'asc') {
        if (!preg_match('/^(asc|desc)$/', $type)) $type = 'asc';
        switch ($by) {
            case 'name':
                $this->sort_field = 'label';
                uasort($this->data, array('Product', 'string_'.$type));
            break;
            case 'date':
                $this->sort_field = 'date_added';
                uasort($this->data, array('Product', 'date_'.$type));
            break;
            default:
                $this->sort_field = 'price';
                uasort($this->data, array('Product', 'num_'.$type));
        }
    }
}

$product = new Product();
$product->get();
$product->sort_by('name');
echo '<pre>'.print_r($product->data, true).'</pre>';
?>

একটি সমাপ্ত নোট হিসাবে, আমি আনুষাঙ্গিকগুলির মতো বৈশিষ্ট্যগুলি সম্পর্কে চিন্তা করি (যা আমি আমার ডেটা পরিবর্তন করতে ব্যবহার করতে পারি)। সহজ রক্ষণাবেক্ষণ, সংক্ষিপ্ত এবং ক্লিনার কোডের জন্য অনুরূপ পদ্ধতি এবং বৈশিষ্ট্য যা আমার ক্লাস থেকে কেটে ফেলা যায় এবং একক জায়গায় রাখা যেতে পারে।


1
যদিও এটি সর্বজনীন ইন্টারফেসকে পরিষ্কার রাখে, অভ্যন্তরীণ এটির সাথে সত্যিই জটিল হয়ে উঠতে পারে, বিশেষত যদি আপনি এটি অন্য জিনিসগুলিতে প্রসারিত করেন যেমন উদাহরণস্বরূপ রঙ। আমি এখানে আরও ভাল সহজ ফাংশন বা স্থির পদ্ধতি মনে করি।
সেবাস্তিয়ান মাচ

আমি এই শব্দটি পছন্দ করি strategies
রানি ওলিট

4

আমি বৈশিষ্ট্যের জন্য উত্সাহিত কারণ তারা যখন একটি মজেন্টো ইকমার্স প্ল্যাটফর্মের জন্য এক্সটেনশানগুলি বিকাশ করে তখন একটি সাধারণ সমস্যা সমাধান করে । সমস্যা দেখা দেয় যখন এক্সটেনশানগুলি একটি বর্ধিতকরণের সাহায্যে কোনও মূল শ্রেণীর (যেমন ব্যবহারকারী মডেল বলে) কার্যকারিতা যুক্ত করে। এটি এক্সটেনশন থেকে ব্যবহারকারী মডেলটি ব্যবহার করতে জেন্ড অটোলোডারকে (একটি এক্সএমএল কনফিগারেশন ফাইলের মাধ্যমে) নির্দেশ করে এবং এই নতুন মডেলের মূল মডেলটি প্রসারিত করার মাধ্যমে করা হয়। ( উদাহরণ ) তবে যদি দুটি এক্সটেনশন একই মডেলকে ওভাররাইড করে? আপনি একটি "রেসের শর্ত" পান এবং কেবলমাত্র একটি লোড করা হয়।

সমাধান এখনই এক্সটেনশানগুলি সম্পাদনা করা যাতে এক অন্যের মডেল ওভাররাইড শ্রেণিকে একটি শৃঙ্খলে প্রসারিত করে এবং তারপরে সঠিক ক্রমে লোড করতে এক্সটেনশন কনফিগারেশন সেট করে যাতে উত্তরাধিকার শৃঙ্খলে কাজ করে।

এই সিস্টেমটি প্রায়শই ত্রুটির সৃষ্টি করে এবং নতুন এক্সটেনশান ইনস্টল করার সময় দ্বন্দ্বগুলি পরীক্ষা করতে এবং এক্সটেনশানগুলি সম্পাদনা করার জন্য এটি প্রয়োজনীয় necessary এটি একটি ব্যথা, এবং আপগ্রেড প্রক্রিয়া ভঙ্গ করে।

আমি মনে করি ট্রাইটস ব্যবহার করা এই বিরক্তিকর মডেলটিকে "রেস শর্ত" ওভাররাইড ছাড়াই একই জিনিসটি সম্পাদন করার একটি ভাল উপায়। অনুমোদিত যে একাধিক বৈশিষ্ট্য একই নামগুলি সহ পদ্ধতিগুলি প্রয়োগ করে তবে এখনও দ্বন্দ্ব হতে পারে, তবে আমি কল্পনা করব যে কোনও সাধারণ নেমস্পেস কনভেনশন এটি বেশিরভাগ অংশে সমাধান করতে পারে।

টিএল; ডিআর আমার ধারণা ট্র্যাজেটগুলি Magento এর মতো বৃহত পিএইচপি সফটওয়্যার প্যাকেজগুলির জন্য এক্সটেনশন / মডিউল / প্লাগইন তৈরি করতে কার্যকর হতে পারে।


0

আপনার কেবলমাত্র পঠনযোগ্য অবজেক্টের জন্য এটির বৈশিষ্ট্য থাকতে পারে:

  trait ReadOnly{  
      protected $readonly = false;

      public function setReadonly($value){ $this->readonly = (bool)$value; }
      public function getReadonly($value){ return $this->readonly; }
  }

সেই বৈশিষ্ট্যটি ব্যবহার করা হয়েছে কিনা তা আপনি সনাক্ত করতে পেরেছিলেন এবং চাকা নির্ধারণ করেছেন কিনা আপনার কোনও ডাটাবেস, ফাইল ইত্যাদিতে সেই বস্তুটি লেখা উচিত নয় not


সুতরাং ক্লাস যে useএই বৈশিষ্ট্য হবে তারপর কল করবে if($this -> getReadonly($value)); তবে আপনি যদি useএই বৈশিষ্ট্যটি না করেন তবে এটি একটি ত্রুটি তৈরি করবে । এর জন্য এই উদাহরণটি ত্রুটিযুক্ত।
Luceos

ঠিক আছে, আপনার বৈশিষ্ট্যটি প্রথমে ব্যবহার করা হচ্ছে কিনা তা পরীক্ষা করা উচিত। যদি ReadOnly বৈশিষ্ট্যটি কোনও সামগ্রীতে সংজ্ঞায়িত করা হয় তবে আপনি এটি কেবল পাঠযোগ্য কিনা তা পরীক্ষা করে দেখতে পারেন।
নিকো


3
আপনার সেই উদ্দেশ্যে ReadOnly এর জন্য একটি ইন্টারফেস ঘোষণা করা উচিত
মাইকেল স্যাং
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.