উপ-টাইপের তালিকায় সুপারটাইপের একটি তালিকা আপনি কীভাবে ফেলেছেন?


244

উদাহরণস্বরূপ, ধরুন আপনার দুটি ক্লাস রয়েছে:

public class TestA {}
public class TestB extends TestA{}

আমার এমন একটি পদ্ধতি রয়েছে যা একটি ফেরত দেয় List<TestA>এবং আমি সেই তালিকাতে সমস্ত বস্তুগুলি কাস্ট করতে চাই TestBযাতে আমি একটি দিয়ে শেষ করি List<TestB>

উত্তর:


578

কেবল List<TestB>প্রায় কাজগুলিতে কাস্টিং ; তবে এটি কার্যকর হয় না কারণ আপনি জেনেরিক ধরণের এক প্যারামিটারটিকে অন্য প্যারামিটারে কাস্ট করতে পারবেন না। তবে, আপনি একটি মধ্যবর্তী ওয়াইল্ডকার্ড প্রকারের মাধ্যমে কাস্ট করতে পারেন এবং এটি অনুমোদিত হবে (যেহেতু আপনি কেবল একটি চেক না করা সতর্কতা সহ ওয়াইল্ডকার্ডের ধরণে এবং করতে পারেন):

List<TestB> variable = (List<TestB>)(List<?>) collectionOfListA;

88
সমস্ত যথাযোগ্য সম্মানের সাথে, আমি মনে করি এটি হ্যাকি সমাধানের ধরণ - আপনি জাভা আপনাকে যে ধরণের সুরক্ষা সরবরাহ করতে চাইছেন তা ধরিয়ে দিচ্ছেন। অন্তত এই জাভা টিউটোরিয়ালটি দেখুন ( docs.oracle.com/javase/tutorial/java/generics/subtyping.html ) এবং কেন এই সমস্যাটি ঠিক করার আগে আপনার এই সমস্যা রয়েছে তা বিবেচনা করুন।
jfritz42

63
@ jfritz42 আমি এটিকে "ডজিং" ধরণের সুরক্ষা বলব না। এই ক্ষেত্রে আপনার জানা আছে যে জাভা নেই। কাস্টিং এর জন্য এটি।
প্ল্যাঙ্কি

3
এটি আমাকে লিখতে দেয়: তালিকা <স্ট্রিং> মাইলিস্ট = (তালিকা <স্ট্রিং>) (তালিকা <?>) (নতুন অ্যারেলিস্ট <Integer> ()); এটি রানটাইমের সময় ক্রাশ হবে। আমি তালিকা <এর মতো কিছু পছন্দ করি? সংখ্যা প্রসারিত> myList = নতুন অ্যারেলিস্ট <Integer> ();
বেন্টায়ে

1
আমি @ jfritz42 এর সাথে সত্যই একমত হয়েছি আমার একই সমস্যা ছিল এবং তিনি যে ইউআরএল সরবরাহ করেছিলেন তা দেখেছি এবং problemালাই ছাড়াই আমার সমস্যা সমাধান করতে সক্ষম হয়েছি।
স্যাম অরোজকো

@ jfritz42 এটি কোনও পূর্ণসংখ্যার অবজেক্ট কাস্ট করা থেকে কার্যকরভাবে আলাদা নয়, যা সংকলক দ্বারা অনুমোদিত
কেসিএল্লারফ

116

জেনেরিকের castালাই সম্ভব নয়, তবে আপনি যদি তালিকাটি অন্য কোনও উপায়ে সংজ্ঞা দেন তবে এতে টেস্টবি সংরক্ষণ করা সম্ভব:

List<? extends TestA> myList = new ArrayList<TestA>();

আপনি তালিকার অবজেক্টগুলি ব্যবহার করার সময় আপনার কাছে এখনও টাইপ চেকিং রয়েছে।


14
এটি বৈধ জাভা সিনট্যাক্সও নয়।
newacct

2
এটি সত্য, তবে এটি
যথার্থরূপে সঠিকর

আমার নিম্নলিখিত পদ্ধতি রয়েছে: createSingleString (তালিকা <? অবজেক্ট> অবজেক্টগুলি প্রসারিত) এই পদ্ধতির অভ্যন্তরে আমি তালিকাটিকে একটি স্ট্রিংয়ে ভেঙে দিতে String.valueOf (অবজেক্ট) বলি। তালিকা <লং>, তালিকা <বুলিয়ান> ইত্যাদি হলে এটি দুর্দান্ত কাজ করে। ধন্যবাদ!
ক্রিস স্প্রেগ

2
টেস্টএ যদি ইন্টারফেস হয়?
সুভিত্রুফ - আন্দ্রেই আপানাসিক

8
আপনি কোথায় এমন এমসিসিই দিতে পারেন যেখানে এটি আসলে কাজ করে? আমি পেতে Cannot instantiate the type ArrayList<? extends TestA>
নাটোয়ামি

42

আপনি সত্যিই পারবেন না *:

উদাহরণটি জাভা টিউটোরিয়াল থেকে নেওয়া হয়েছে

ধরুন এখানে দুটি প্রকার Aএবং Bএরকম রয়েছে B extends A। তারপরে নিম্নলিখিত কোডটি সঠিক:

    B b = new B();
    A a = b;

পূর্ববর্তী কোডটি বৈধ কারণ Bএটি একটি সাবক্লাস A। এখন, কি দিয়ে ঘটবে List<A>এবং List<B>?

দেখা যাচ্ছে যে List<B>এটি একটি সাবক্লাস নয় List<A>তাই আমরা লিখতে পারি না

    List<B> b = new ArrayList<>();
    List<A> a = b; // error, List<B> is not of type List<A>

তদুপরি, আমরা এমনকি লিখতে পারি না

    List<B> b = new ArrayList<>();
    List<A> a = (List<A>)b; // error, List<B> is not of type List<A>

*: সম্ভব ভোটদান করতে আমরা উভয় জন্য একটি সাধারণ পিতা বা মাতা প্রয়োজন List<A>এবং List<B>: List<?>উদাহরণস্বরূপ। নিম্নলিখিত হল বৈধ:

    List<B> b = new ArrayList<>();
    List<?> t = (List<B>)b;
    List<A> a = (List<A>)t;

আপনি তবে একটি সতর্কতা পাবেন। আপনি @SuppressWarnings("unchecked")আপনার পদ্ধতিতে যুক্ত করে এটি দমন করতে পারেন ।


2
এছাড়াও, এই লিঙ্কের উপাদানগুলি ব্যবহার করা অনিচ্ছুক রূপান্তর এড়াতে পারে, যেহেতু সংকলক পুরো রূপান্তরটি বোঝাতে পারে।
রায়ান এইচ

29

জাভা 8 দিয়ে, আপনি আসলে পারেন

List<TestB> variable = collectionOfListA
    .stream()
    .map(e -> (TestB) e)
    .collect(Collectors.toList());

32
আসলেই কি তালিকার তালিকাই দেওয়া হচ্ছে? কারণ এটি পুরো তালিকার পুনরাবৃত্তি করতে প্রতিটি উপাদানকে কাস্ট করে, এবং তারপরে সেগুলি পছন্দসই ধরণের নতুন ইনস্ট্যান্টিয়েটেড তালিকায় যুক্ত করার মতো ক্রিয়াকলাপগুলির মতো আরও পড়ে। অন্যভাবে বলুন, আপনি জাভা with- এর সাথে একটি new List<TestB>, লুপ এবং a ালাই দিয়ে ঠিক এটি করতে পারবেন না ?
প্যাট্রিক এম

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

17

আমি মনে করি আপনি ভুল পথে কাস্ট করছেন যদিও ... যদি পদ্ধতিটি কোনও জিনিসের একটি তালিকা ফিরিয়ে দেয় TestAতবে তাদের কাছে ফেলে দেওয়া সত্যই নিরাপদ নয় TestB

মূলত আপনি সংকলককে এমন কোনও TestBধরণের অপারেশন করার জন্য বলছেন যা TestAতাদের সমর্থন করে না।


11

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


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


অবশ্যই, কাস্টগুলি বৈধ হতে পারে। সংকলকটির জন্য উপলভ্য নয় এমন প্রকারগুলি সম্পর্কে আপনার মাঝে মাঝে তথ্য থাকে। এই ক্ষেত্রে, তালিকা কাস্ট করা সম্ভব, তবে সাধারণভাবে এটি সুপারিশ করা হয় না :

কেউ হয় ...

  • ... পুরো তালিকা কাস্ট করুন বা
  • ... তালিকার সমস্ত উপাদান নিক্ষেপ করুন

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

এই স্পিউরিয়াস ডিবাগিংয়ের সমস্যাগুলি পদ্ধতির পরিবারের ClassCastExceptionsসাথে উপশম করা যেতে পারে Collections#checkedCollection


টাইপের উপর ভিত্তি করে তালিকা ফিল্টার করা হচ্ছে

A থেকে রূপান্তর একটি আরো টাইপ-নিরাপদ উপায় List<Supertype> একটি থেকে List<Subtype>আসলে হয় ফিল্টার তালিকা এবং একটি নতুন তালিকা নির্দিষ্ট ধরনের আছে যেটি শুধুমাত্র উপাদানগুলি রয়েছে তৈরি করুন। এই জাতীয় পদ্ধতি প্রয়োগের জন্য স্বাধীনতার কিছু ডিগ্রি রয়েছে (উদাহরণস্বরূপ nullএন্ট্রিগুলির চিকিত্সা সম্পর্কিত ), তবে একটি সম্ভাব্য বাস্তবায়ন এর মতো হতে পারে:

/**
 * Filter the given list, and create a new list that only contains
 * the elements that are (subtypes) of the class c
 * 
 * @param listA The input list
 * @param c The class to filter for
 * @return The filtered list
 */
private static <T> List<T> filter(List<?> listA, Class<T> c)
{
    List<T> listB = new ArrayList<T>();
    for (Object a : listA)
    {
        if (c.isInstance(a))
        {
            listB.add(c.cast(a));
        }
    }
    return listB;
}

এই পদ্ধতিটি স্বেচ্ছাচারিত তালিকাগুলি ফিল্টার করতে ব্যবহার করা যেতে পারে (কেবলমাত্র টাইপ পরামিতিগুলির সাথে প্রদত্ত সাব-টাইপ-সুপার টাইপের সম্পর্কের সাথে নয়), যেমন এই উদাহরণটিতে:

// A list of type "List<Number>" that actually 
// contains Integer, Double and Float values
List<Number> mixedNumbers = 
    new ArrayList<Number>(Arrays.asList(12, 3.4, 5.6f, 78));

// Filter the list, and create a list that contains
// only the Integer values:
List<Integer> integers = filter(mixedNumbers, Integer.class);

System.out.println(integers); // Prints [12, 78]

7

আপনি নিক্ষেপ করতে পারবে না List<TestB>থেকে List<TestA>যেমন স্টিভ Kuo থেকে উল্লেখ কিন্তু আপনি বিষয়বস্তু ডাম্প করতে List<TestA>মধ্যে List<TestB>। নিম্নলিখিত চেষ্টা করুন:

List<TestA> result = new List<TestA>();
List<TestB> data = new List<TestB>();
result.addAll(data);

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


কেন এই ডাউন ভোট দেওয়া হয়েছে? এটি আমার পক্ষে কার্যকর ছিল এবং আমি নিচের ভোটের কোনও ব্যাখ্যা দেখতে পাচ্ছি না।
জোড

7
অবশ্যই এই পোস্টটি ভুল নয়। তবে যে ব্যক্তি প্রশ্নটি করেছিল তার শেষ পর্যন্ত টেস্টবিয়ের একটি তালিকা দরকার। সেক্ষেত্রে এই উত্তরটি বিভ্রান্তিকর। আপনি তালিকা <টেস্টবি> তালিকায় সমস্ত উপাদান যুক্ত করতে পারেন <টেস্টএ> তালিকায় <টেস্টা> .এডএলএল (তালিকা <টেস্টবি>) কল করে। তবে আপনি তালিকাটি <টেস্টবি> ব্যবহার করতে পারবেন না adএডএলএল (তালিকা <টেস্টা>);

6

সর্বোত্তম নিরাপদ উপায় হ'ল বাস্তবায়নে কোনও AbstractListআইটেম প্রয়োগ করা। আমি ListUtilসহায়ক শ্রেণি তৈরি করেছি :

public class ListUtil
{
    public static <TCastTo, TCastFrom extends TCastTo> List<TCastTo> convert(final List<TCastFrom> list)
    {
        return new AbstractList<TCastTo>() {
            @Override
            public TCastTo get(int i)
            {
                return list.get(i);
            }

            @Override
            public int size()
            {
                return list.size();
            }
        };
    }

    public static <TCastTo, TCastFrom> List<TCastTo> cast(final List<TCastFrom> list)
    {
        return new AbstractList<TCastTo>() {
            @Override
            public TCastTo get(int i)
            {
                return (TCastTo)list.get(i);
            }

            @Override
            public int size()
            {
                return list.size();
            }
        };
    }
}

castতালিকাভুক্ত ও convertনিরাপদ ingালাইয়ের জন্য পদ্ধতিতে অন্ধভাবে কাস্ট করার পদ্ধতি আপনি ব্যবহার করতে পারেন । উদাহরণ:

void test(List<TestA> listA, List<TestB> listB)
{
    List<TestB> castedB = ListUtil.cast(listA); // all items are blindly casted
    List<TestB> convertedB = ListUtil.<TestB, TestA>convert(listA); // wrong cause TestA does not extend TestB
    List<TestA> convertedA = ListUtil.<TestA, TestB>convert(listB); // OK all items are safely casted
}

4

আমার জানা একমাত্র উপায় হ'ল অনুলিপি করা:

List<TestB> list = new ArrayList<TestB> (
    Arrays.asList (
        testAList.toArray(new TestB[0])
    )
);

2
বেশ আশ্চর্যজনক আমি মনে করি এটি একটি সংকলক সতর্কতা দেয় না।
সাইমন ফোর্সবার্গ

এটি অ্যারেগুলির সাথে একটি বিজোড়তা। দীর্ঘশ্বাস, জাভা অ্যারে তাই অকেজো। তবে, আমি মনে করি এটি অন্যান্য উত্তরগুলির চেয়ে অবশ্যই খারাপ নয় এবং খুব বেশি পাঠযোগ্য। আমি এটি আর কাস্টের চেয়ে অসুরক্ষিত দেখতে পাচ্ছি না।
থুফির

3

আপনি যখন কোনও অবজেক্ট রেফারেন্স কাস্ট করেন আপনি কেবলমাত্র রেফারেন্সের প্রকারটি ingালাই করছেন, বস্তুর ধরণ নয়। ingালাই বস্তুর প্রকৃত ধরণের পরিবর্তন করবে না।

জাভাতে অবজেক্টের ধরণের রূপান্তরিত করার জন্য অন্তর্নিহিত নিয়ম নেই। (আদিমদের মতো নয়)

পরিবর্তে আপনাকে কীভাবে এক প্রকারকে অন্য ধরণের রূপান্তর করতে হবে এবং ম্যানুয়ালি কল করতে হবে।

public class TestA {}
public class TestB extends TestA{ 
    TestB(TestA testA) {
        // build a TestB from a TestA
    }
}

List<TestA> result = .... 
List<TestB> data = new List<TestB>();
for(TestA testA : result) {
   data.add(new TestB(testA));
}

এটি সরাসরি সমর্থন সহ কোনও ভাষার চেয়ে ভার্জোজ, তবে এটি কার্যকর হয় এবং আপনার এটি খুব ঘন ঘন করার প্রয়োজন হবে না।


2

আপনার যদি ক্লাসের কোনও বিষয় থাকে তবে আপনি TestAএটি কাস্ট করতে পারবেন না TestB। প্রত্যেকটি TestBএকটি TestA, তবে অন্যভাবে নয়।

নিম্নলিখিত কোডে:

TestA a = new TestA();
TestB b = (TestB) a;

দ্বিতীয় লাইন একটি নিক্ষেপ করা হবে ClassCastException

আপনি কেবলমাত্র কোনও TestAরেফারেন্স দিতে পারেন যদি বস্তুটি নিজেই হয় TestB। উদাহরণ স্বরূপ:

TestA a = new TestB();
TestB b = (TestB) a;

তাই হয়, আপনি সবসময় একটি তালিকার নিক্ষেপ নাও হতে পারে TestAএকটি তালিকায় TestB


1
আমি মনে করি তিনি এই জাতীয় কিছু নিয়ে কথা বলছেন, আপনি একটি পদ্ধতির যুক্তি হিসাবে 'a' পাবেন যা টেস্টএ এ = নতুন টেস্টবি () হিসাবে তৈরি করা হয়, তারপরে আপনি টেস্টবি অবজেক্টটি পেতে চান এবং তারপরে আপনাকে এটি নিক্ষেপ করা দরকার - টেস্টবি বি = ( টেস্টবি) ক;
সামসমার

2

আপনি Eclipse সংগ্রহেselectInstances পদ্ধতিটি ব্যবহার করতে পারেন । এটি কোনও নতুন সংগ্রহ তৈরির সাথে জড়িত থাকবে তবে তাই কাস্টিং ব্যবহার করা গৃহীত সমাধানের মতো দক্ষ হবে না।

List<CharSequence> parent =
        Arrays.asList("1","2","3", new StringBuffer("4"));
List<String> strings =
        Lists.adapt(parent).selectInstancesOf(String.class);
Assert.assertEquals(Arrays.asList("1","2","3"), strings);

আমি StringBufferউদাহরণটি অন্তর্ভুক্ত করে দেখানোর জন্য যে selectInstancesকেবল টাইপটিকেই হ্রাস করে না, তবে সংগ্রহে মিশ্রিত প্রকারগুলি থাকলে ফিল্টারও করা হবে।

দ্রষ্টব্য: আমি গ্রহগ্রাহ সংগ্রহের প্রতিশ্রুতিবদ্ধ।


1

টাইপ ইরেজরের কারণে এটি সম্ভব। আপনি এটি পাবেন

List<TestA> x = new ArrayList<TestA>();
List<TestB> y = new ArrayList<TestB>();
x.getClass().equals(y.getClass()); // true

অভ্যন্তরীণভাবে উভয় তালিকাই ধরণের List<Object>। সেই কারণে আপনি একজনকে অন্যকে কাস্ট করতে পারবেন না - castালার মতো কিছুই নেই।


"কাস্ট করার কিছু নেই" এবং "আপনি অন্যকে কাস্ট করতে পারবেন না" কিছুটা দ্বন্দ্ব। Integer j = 42; Integer i = (Integer) j;দুর্দান্ত কাজ করে, উভয়ই পূর্ণসংখ্যা, তাদের উভয়েরই একই শ্রেণি রয়েছে, সুতরাং "castালার কিছুই নেই"।
সাইমন ফোর্সবার্গ

1

সমস্যাটি হ'ল যদি আপনার পদ্ধতিতে টেস্টবি থাকে তবে টেস্টএর একটি তালিকা ফেরত দেয় না, তাই যদি এটি সঠিকভাবে টাইপ করা হত? তারপরে এই কাস্ট:

class TestA{};
class TestB extends TestA{};
List<? extends TestA> listA;
List<TestB> listB = (List<TestB>) listA;

আপনি আশা করতে পারেন পাশাপাশি কাজ করে (Eclipse একটি যাচাই না করা কাস্ট সম্পর্কে সতর্ক করে যা আপনি যা করছেন ঠিক তাই, তাই)) সুতরাং আপনি কি আপনার সমস্যা সমাধানের জন্য এটি ব্যবহার করতে পারেন? আসলে আপনি এই কারণে করতে পারেন:

List<TestA> badlist = null; // Actually contains TestBs, as specified
List<? extends TestA> talist = badlist;  // Umm, works
List<TextB> tblist = (List<TestB>)talist; // TADA!

ঠিক আপনি যা চেয়েছিলেন, তাই না? বা সত্যিই সঠিক হতে হবে:

List<TestB> tblist = (List<TestB>)(List<? extends TestA>) badlist;

আমার জন্য ঠিক জরিমানা সংকলন বলে মনে হচ্ছে।


1
class MyClass {
  String field;

  MyClass(String field) {
    this.field = field;
  }
}

@Test
public void testTypeCast() {
  List<Object> objectList = Arrays.asList(new MyClass("1"), new MyClass("2"));

  Class<MyClass> clazz = MyClass.class;
  List<MyClass> myClassList = objectList.stream()
      .map(clazz::cast)
      .collect(Collectors.toList());

  assertEquals(objectList.size(), myClassList.size());
  assertEquals(objectList, myClassList);
}

এই পরীক্ষাটি কীভাবে কাস্ট List<Object>করা যায় তা দেখায় List<MyClass>। তবে আপনাকে অবশ্যই মনোযোগ দেওয়া দরকার যা objectListঅবশ্যই একই ধরণের উদাহরণগুলির সাথে থাকতে পারে MyClass। এবং এই উদাহরণটি কখন List<T>ব্যবহৃত হয় তা বিবেচনা করা যেতে পারে । এই উদ্দেশ্যে Class<T> clazzকনস্ট্রাক্টারে ক্ষেত্র পান এবং এর পরিবর্তে এটি ব্যবহার করুন MyClass.class


0

এটি কাজ করা উচিত

List<TestA> testAList = new ArrayList<>();
List<TestB> testBList = new ArrayList<>()
testAList.addAll(new ArrayList<>(testBList));

1
এটি একটি অপ্রয়োজনীয় অনুলিপি তৈরি করে।
ডিফনুল

0

বেশ আশ্চর্যের বিষয় যে ম্যানুয়ালি একটি তালিকা ingালাই এখনও কিছু সরঞ্জাম বাক্স দ্বারা সরবরাহ করা হয়নি যেমন কিছু প্রয়োগ করে:

@SuppressWarnings({ "unchecked", "rawtypes" })
public static <T extends E, E> List<T> cast(List<E> list) {
    return (List) list;
}

অবশ্যই, এটি একের পর এক আইটেমগুলি পরীক্ষা করবে না, তবে এটি এখানে আমরা অবশ্যই এড়াতে চাই, যদি আমরা ভালভাবে জানি যে আমাদের বাস্তবায়ন কেবল উপ-প্রকার সরবরাহ করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.