কোটলিনে সংশোধিত কীওয়ার্ডটি কীভাবে কাজ করে?


144

আমি reifiedকীওয়ার্ডের উদ্দেশ্যটি বোঝার চেষ্টা করছি , স্পষ্টতই এটি আমাদের জেনেরিকের প্রতিচ্ছবি করতে দেয়

যাইহোক, আমি এটি ছেড়ে দিলে এটি ঠিক ঠিক কাজ করে। কেউ যখন বোঝাতে আগ্রহী এটি কখন একটি বাস্তব পার্থক্য করে ?


আপনি কি নিশ্চিত যে প্রতিফলন কি জানেন? এছাড়াও, আপনি মুছে যাওয়ার ধরণ সম্পর্কে শুনেছেন?
মিবাক

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

এটি প্রতিবিম্বের উপর নির্ভর না করে এবং যুক্তি হিসাবে প্রকারটি পাস না করে কোনও ফাংশনের কংক্রিট জেনেরিক ধরণের অ্যাক্সেস পেতে দেয়।
ব্লেডকডার

উত্তর:


368

টিএল; ডিআর: কী জন্য reifiedভাল

fun <T> myGenericFun(c: Class<T>) 

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

আপনি যদি inlineকোনও রিফাইড দিয়ে কোনও ফাংশন তৈরি করেন তবে রানটাইমের সময়ও এ Tধরণের Tঅ্যাক্সেস পাওয়া যায় এবং সুতরাং আপনাকে Class<T>অতিরিক্তভাবে পাস করার দরকার নেই । আপনার সাথে কাজ করতে Tযেমন যদি এটা একটি স্বাভাবিক বর্গ ছিল, যেমন আপনি একটি পরিবর্তনশীল একটি কিনা চেক করতে চান পারে দৃষ্টান্ত T , যা আপনি সহজে তারপর করতে পারেন: myVar is T

টাইপ inlineসহ এই জাতীয় ফাংশন নীচে দেখায়:reifiedT

inline fun <reified T> myGenericFun()

কিভাবে reifiedকাজ করে

আপনি কেবল reifiedকোনও inlineফাংশনের সংমিশ্রণে ব্যবহার করতে পারেন । এই জাতীয় ফাংশন কম্পাইলার যেখানে ফাংশনটি ব্যবহৃত হচ্ছে সেখানে ফাংশনের বাইকোড অনুলিপি করে (ফাংশনটি "ইনলাইনড" হচ্ছে)। আপনি যখন সংশোধিত প্রকারের সাথে একটি ইনলাইন ফাংশনটি কল করবেন তখন সংকলকটি টাইপ আর্গুমেন্ট হিসাবে ব্যবহৃত প্রকৃত প্রকারটি জানে এবং সরাসরি সংশ্লিষ্ট বর্গটি ব্যবহার করতে উত্পন্ন বাইকোডকে সংশোধন করে। সুতরাং বাইটকোডে এবং রানটাইমে কল myVar is Tহয়ে ওঠার মতো কল myVar is String(যদি প্রকারের যুক্তিটি ছিল String)।


উদাহরণ

আসুন একটি উদাহরণ দেখুন যা দেখায় যে কতটা সহায়ক reifiedহতে পারে। আমরা Stringযার জন্য একটি এক্সটেনশন ফাংশন তৈরি করতে চাই toKotlinObjectযা ফাংশনের জেনেরিক ধরণ দ্বারা নির্দিষ্ট একটি প্রকারের সাথে একটি JSON স্ট্রিংকে একটি সরল কোটলিন অবজেক্টে রূপান্তরিত করার চেষ্টা করে T। আমরা এটির com.fasterxml.jackson.module.kotlinজন্য ব্যবহার করতে পারি এবং প্রথম পদ্ধতিটি নিম্নলিখিত:

ক) সংশোধিত প্রকার ছাড়াই প্রথম পন্থা

fun <T> String.toKotlinObject(): T {
      val mapper = jacksonObjectMapper()
                                                        //does not compile!
      return mapper.readValue(this, T::class.java)
}

readValueপদ্ধতি একটি টাইপ এটি বিশ্লেষণ করতে অনুমিত এর লাগে JsonObjectকরতে। যদি আমরা Classটাইপ প্যারামিটারটি পেতে চেষ্টা করি T, সংকলকটি অভিযোগ করে: "'টি' রিফাইড টাইপ প্যারামিটার হিসাবে ব্যবহার করতে পারবেন না instead পরিবর্তে একটি শ্রেণি ব্যবহার করুন" "

খ) সুস্পষ্ট Classপ্যারামিটারের সাথে কাজ করা

fun <T: Any> String.toKotlinObject(c: KClass<T>): T {
    val mapper = jacksonObjectMapper()
    return mapper.readValue(this, c.java)
}

একটি ওয়ার্কঅ্যারাউন্ড হিসেবে Classএর Tএকটি পদ্ধতি প্যারামিটার, যা একটি যুক্তি হিসেবে ব্যবহার করা যেতে পারে readValue। এটি কাজ করে এবং জেনেরিক জাভা কোডের একটি সাধারণ প্যাটার্ন। এটি নিম্নলিখিত হিসাবে বলা যেতে পারে:

data class MyJsonType(val name: String)

val json = """{"name":"example"}"""
json.toKotlinObject(MyJsonType::class)

গ) কোটলিন পথ: reified

টাইপ প্যারামিটার inlineসহ একটি ফাংশন ব্যবহার করে ফাংশনটিকে ভিন্নভাবে প্রয়োগ করা সম্ভব করে তোলে:reifiedT

inline fun <reified T: Any> String.toKotlinObject(): T {
    val mapper = jacksonObjectMapper()
    return mapper.readValue(this, T::class.java)
}

গ্রহণ করার কোন প্রয়োজন নেই Classএর Tঅতিরিক্ত হিসাবে, Tব্যবহার করা যেতে পারে যেমন যদি এটা একজন সাধারণ বর্গ ছিল। ক্লায়েন্টের জন্য কোডটি দেখতে এরকম দেখাচ্ছে:

json.toKotlinObject<MyJsonType>()

গুরুত্বপূর্ণ দ্রষ্টব্য: জাভা নিয়ে কাজ করা

সহ একটি inlined ফাংশন reifiedধরনের জাভা থেকে callable না কোড।


6
আপনার ব্যাপক প্রতিক্রিয়া জন্য ধন্যবাদ! যে আসলে জ্ঞান করে। কেবলমাত্র একটি জিনিস আমি ভাবছি, ফাংশনটি যাইহোক ইনডিল করা হচ্ছে তবে কেন পুনরায় সংশোধন করা দরকার? এটি মুছে যাওয়ার ধরণটি ছেড়ে দিবে এবং যাইহোক ফাংশনটি ইনলাইন করবে? এটি আমার কাছে এক ধরণের অপব্যয় বলে মনে হয়, আপনি যদি ফাংশনটি ইনলাইন করেন তবে আপনি যে ধরণের ব্যবহার করছেন তা ইনলাইনও করতে পারেন বা আমি এখানে কিছু ভুল দেখছি?
hl3mukkel

6
আপনার মতামতের জন্য ধন্যবাদ, আসলে আমি এমন কিছু উল্লেখ করতে ভুলে গেছি যা আপনাকে উত্তর দিতে পারে: একটি সাধারণ ইনলাইন ফাংশন জাভা থেকে কল করা যেতে পারে তবে একটি রাইফাইড টাইপ প্যারামিটার সহ একটি করতে পারে না! আমি মনে করি এটি একটি কারণ যা একটি ইনলাইন ফাংশনের প্রতিটি ধরণের প্যারামিটার স্বয়ংক্রিয়ভাবে পুনরায় সংস্কার করা হয় না।
s1m0nw1

যদি ফাংশনটি সংশোধিত এবং অ-সংশোধিত পরামিতিগুলির মিশ্রণ হয়? এটি জাভা থেকে যে কোনও উপায়ে ডাকার যোগ্য নয়, কেন সমস্ত ধরণের পরামিতিগুলি স্বয়ংক্রিয়ভাবে পুনরায় সংশোধন করবে না? কোটলিনকে সমস্ত ধরণের প্যারামিটারের জন্য স্পষ্টভাবে পুনরায় সংশোধন করা দরকার কেন?
ভাইরাওয়ান

1
যদি স্ট্যাকের উপরের কলারদের json.toKotlinObject <MyJsonType> () না, তবে json.toKotlinObject <T> () বিভিন্ন বস্তুর জন্য প্রয়োজন হয়?
সাত

1

সহজ

* সংশোধনকালে সংশোধন করার সময় ব্যবহারের অনুমতি দেওয়ার জন্য রিফাইড করা হয়েছে (ডি ফাংশনের ভিতরে টি অ্যাক্সেস করতে)

উদাহরণ:

 inline fun <reified T:Any>  String.convertToObject(): T{

    val gson = Gson()

    return gson.fromJson(this,T::class.java)

}

মত ব্যবহার:

val jsonStringResponse = "{"name":"bruno" , "age":"14" , "world":"mars"}"
val userObject = jsonStringResponse.convertToObject<User>()
  println(user.name)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.