এই কোডল্যাবটি প্রোগ্রামারদের কোর্সের জন্য কোটলিন বুটক্যাম্পের অংশ। আপনি যদি ক্রমানুসারে কোডল্যাবগুলির মাধ্যমে কাজ করেন তবে আপনি এই কোর্সের সর্বাধিক মূল্য পাবেন৷ আপনার জ্ঞানের উপর নির্ভর করে, আপনি কিছু বিভাগ স্কিম করতে সক্ষম হতে পারেন। এই কোর্সটি এমন প্রোগ্রামারদের জন্য তৈরি যারা একটি অবজেক্ট-ওরিয়েন্টেড ভাষা জানেন এবং কোটলিন শিখতে চান।
ভূমিকা
এই কোডল্যাবে আপনাকে জেনেরিক ক্লাস, ফাংশন এবং পদ্ধতি এবং তারা কোটলিনে কীভাবে কাজ করে তার সাথে পরিচয় করিয়ে দেওয়া হয়েছে।
একটি একক নমুনা অ্যাপ তৈরি করার পরিবর্তে, এই কোর্সের পাঠগুলি আপনার জ্ঞান তৈরি করার জন্য ডিজাইন করা হয়েছে, তবে একে অপরের থেকে আধা-স্বতন্ত্র থাকুন যাতে আপনি আপনার পরিচিত বিভাগগুলিকে স্কিম করতে পারেন। তাদের একসাথে বাঁধতে, অনেক উদাহরণ একটি অ্যাকোয়ারিয়াম থিম ব্যবহার করে। এবং আপনি যদি সম্পূর্ণ অ্যাকোয়ারিয়ামের গল্প দেখতে চান, তাহলে প্রোগ্রামারদের জন্য কোটলিন বুটক্যাম্প উদাসিটি কোর্সটি দেখুন।
আপনি ইতিমধ্যে কি জানা উচিত
- কোটলিন ফাংশন, ক্লাস এবং পদ্ধতির সিনট্যাক্স
- কিভাবে IntelliJ IDEA এ একটি নতুন ক্লাস তৈরি করবেন এবং একটি প্রোগ্রাম চালাবেন
আপনি কি শিখবেন
- জেনেরিক ক্লাস, পদ্ধতি এবং ফাংশনগুলির সাথে কীভাবে কাজ করবেন
আপনি কি করবেন
- একটি জেনেরিক ক্লাস তৈরি করুন এবং সীমাবদ্ধতা যোগ করুন
-
inএবংoutপ্রকার তৈরি করুন - জেনেরিক ফাংশন, পদ্ধতি, এবং এক্সটেনশন ফাংশন তৈরি করুন
জেনেরিকের পরিচিতি
অনেক প্রোগ্রামিং ভাষার মতো কোটলিনেরও জেনেরিক প্রকার রয়েছে। একটি জেনেরিক টাইপ আপনাকে একটি ক্লাস জেনেরিক করতে দেয় এবং এর ফলে একটি ক্লাসকে অনেক বেশি নমনীয় করে তোলে।
কল্পনা করুন যে আপনি একটি MyList ক্লাস বাস্তবায়ন করছেন যা আইটেমগুলির একটি তালিকা ধারণ করে। জেনেরিক ছাড়া, আপনাকে প্রতিটি প্রকারের জন্য MyList এর একটি নতুন সংস্করণ বাস্তবায়ন করতে হবে: একটি Double এর জন্য, একটি String এর জন্য, একটি Fish এর জন্য। জেনেরিকের সাহায্যে, আপনি তালিকাটিকে জেনেরিক করতে পারেন, তাই এটি যেকোন ধরণের বস্তুকে ধরে রাখতে পারে। এটি টাইপটিকে একটি ওয়াইল্ডকার্ড বানানোর মতো যা অনেক ধরণের ফিট হবে।
একটি জেনেরিক টাইপ সংজ্ঞায়িত করতে, ক্লাসের নামের পরে কোণ বন্ধনী <T> এ T লিখুন। (আপনি অন্য অক্ষর বা একটি দীর্ঘ নাম ব্যবহার করতে পারেন, কিন্তু একটি জেনেরিক টাইপের কনভেনশন হল টি।)
class MyList<T> {
fun get(pos: Int): T {
TODO("implement")
}
fun addItem(item: T) {}
} আপনি T উল্লেখ করতে পারেন যেন এটি একটি স্বাভাবিক প্রকার। get() এর রিটার্ন টাইপ হল T , এবং addItem() এর প্যারামিটারটি T টাইপ। অবশ্যই, জেনেরিক তালিকাগুলি খুব দরকারী, তাই List ক্লাসটি কোটলিনে তৈরি করা হয়েছে।
ধাপ 1: একটি টাইপ অনুক্রম তৈরি করুন
এই ধাপে আপনি পরবর্তী ধাপে ব্যবহার করার জন্য কিছু ক্লাস তৈরি করুন। সাবক্লাসিং একটি আগের কোডল্যাবে আচ্ছাদিত ছিল, কিন্তু এখানে একটি সংক্ষিপ্ত পর্যালোচনা।
- উদাহরণটি অগোছালো রাখতে, src এর অধীনে একটি নতুন প্যাকেজ তৈরি করুন এবং এটিকে
genericsবলুন। - জেনেরিক প্যাকেজে, একটি নতুন
Aquarium.ktফাইল তৈরি করুন। এটি আপনাকে বিরোধ ছাড়াই একই নাম ব্যবহার করে জিনিসগুলিকে পুনরায় সংজ্ঞায়িত করতে দেয়, তাই এই কোডল্যাবের জন্য আপনার বাকি কোডটি এই ফাইলে যায়৷ - জল সরবরাহের ধরনগুলির একটি প্রকার শ্রেণিবিন্যাস করুন।
WaterSupplyএকটিopenক্লাস বানিয়ে শুরু করুন, যাতে এটি সাবক্লাস করা যায়। - একটি বুলিয়ান
varপ্যারামিটার যোগ করুন,needsProcessing। এটি স্বয়ংক্রিয়ভাবে একটি পরিবর্তনযোগ্য সম্পত্তি তৈরি করে, একটি গেটার এবং সেটারের সাথে। - একটি সাবক্লাস
TapWaterতৈরি করুন যাWaterSupplyপ্রসারিত করে এবংneedsProcessingজন্যtrueপাস করে, কারণ কলের জলে অ্যাডিটিভ থাকে যা মাছের জন্য খারাপ। -
TapWaterএ,addChemicalCleaners()নামক একটি ফাংশন সংজ্ঞায়িত করুন যা জল পরিষ্কার করার পরেneedsProcessingকেfalseসেট করে।needsProcessingসম্পত্তিTapWaterথেকে সেট করা যেতে পারে, কারণ এটি ডিফল্টরূপেpublicএবং সাবক্লাসে অ্যাক্সেসযোগ্য। এখানে সম্পূর্ণ কোড আছে.
package generics
open class WaterSupply(var needsProcessing: Boolean)
class TapWater : WaterSupply(true) {
fun addChemicalCleaners() {
needsProcessing = false
}
}-
FishStoreWaterএবংLakeWaterনামেWaterSupplyআরও দুটি উপশ্রেণী তৈরি করুন।FishStoreWaterপ্রক্রিয়াকরণের প্রয়োজন নেই, তবেLakeWaterfilter()পদ্ধতিতে ফিল্টার করতে হবে। ফিল্টার করার পরে, এটিকে আবার প্রসেস করার দরকার নেই, তাইfilter()এ,needsProcessing = falseসেট করুন।
class FishStoreWater : WaterSupply(false)
class LakeWater : WaterSupply(true) {
fun filter() {
needsProcessing = false
}
}আপনার যদি অতিরিক্ত তথ্যের প্রয়োজন হয়, কোটলিনে উত্তরাধিকার সম্পর্কিত পূর্ববর্তী পাঠটি পর্যালোচনা করুন।
ধাপ 2: একটি জেনেরিক ক্লাস তৈরি করুন
এই ধাপে আপনি বিভিন্ন ধরনের জল সরবরাহ সমর্থন করার জন্য Aquarium শ্রেণী পরিবর্তন করেন।
- Aquarium.kt- এ, ক্লাসের নামের পরে বন্ধনীতে
<T>সহ একটিAquariumক্লাস সংজ্ঞায়িত করুন। -
AquariumTটাইপের একটি অপরিবর্তনীয় সম্পত্তিwaterSupplyযোগ করুন।
class Aquarium<T>(val waterSupply: T)-
genericsExample()নামে একটি ফাংশন লিখুন। এটি একটি ক্লাসের অংশ নয়, তাই এটি ফাইলের শীর্ষ স্তরে যেতে পারে, যেমনmain()ফাংশন বা ক্লাস সংজ্ঞা। ফাংশনে, একটিAquariumতৈরি করুন এবং এটিকে একটিWaterSupplyসরবরাহ করুন। যেহেতুwaterSupplyপ্যারামিটারটি জেনেরিক, তাই আপনাকে অবশ্যই এঙ্গেল ব্র্যাকেটে ধরনটি উল্লেখ করতে হবে<>।
fun genericsExample() {
val aquarium = Aquarium<TapWater>(TapWater())
}-
genericsExample()এ আপনার কোড অ্যাকোয়ারিয়ামেরwaterSupplyঅ্যাক্সেস করতে পারে। কারণ এটিTapWaterটাইপের, আপনি কোনো প্রকার কাস্ট ছাড়াইaddChemicalCleaners()কল করতে পারেন।
fun genericsExample() {
val aquarium = Aquarium<TapWater>(TapWater())
aquarium.waterSupply.addChemicalCleaners()
}-
Aquariumঅবজেক্ট তৈরি করার সময়, আপনি কোণ বন্ধনী এবং তাদের মধ্যে কী আছে তা সরিয়ে ফেলতে পারেন কারণ কোটলিনের টাইপ অনুমান রয়েছে। সুতরাং আপনি যখন উদাহরণ তৈরি করবেন তখনTapWaterদুবার বলার কোন কারণ নেই। ধরণটিAquariumযুক্তি দ্বারা অনুমান করা যেতে পারে; এটি এখনওTapWaterটাইপের একটিAquariumতৈরি করবে।
fun genericsExample() {
val aquarium = Aquarium(TapWater())
aquarium.waterSupply.addChemicalCleaners()
}- কি ঘটছে তা দেখতে,
addChemicalCleaners()কল করার আগে এবং পরে প্রিন্টেরneedsProcessing। নীচে সম্পন্ন ফাংশন আছে.
fun genericsExample() {
val aquarium = Aquarium<TapWater>(TapWater())
println("water needs processing: ${aquarium.waterSupply.needsProcessing}")
aquarium.waterSupply.addChemicalCleaners()
println("water needs processing: ${aquarium.waterSupply.needsProcessing}")
}-
genericsExample()কল করতে একটিmain()ফাংশন যোগ করুন, তারপর আপনার প্রোগ্রামটি চালান এবং ফলাফলটি পর্যবেক্ষণ করুন।
fun main() {
genericsExample()
}⇒ water needs processing: true water needs processing: false
ধাপ 3: এটি আরও নির্দিষ্ট করুন
জেনেরিক মানে আপনি প্রায় যেকোনো কিছু পাস করতে পারেন এবং কখনও কখনও এটি একটি সমস্যা। এই ধাপে আপনি Aquarium শ্রেণীকে আরও সুনির্দিষ্ট করে তোলেন যে আপনি এতে কী রাখতে পারেন।
-
genericsExample()-এ, একটিAquariumতৈরি করুন,waterSupplyজন্য একটি স্ট্রিং পাস করুন, তারপর অ্যাকোয়ারিয়ামেরwaterSupplyসম্পত্তি প্রিন্ট করুন৷
fun genericsExample() {
val aquarium2 = Aquarium("string")
println(aquarium2.waterSupply)
}- আপনার প্রোগ্রাম চালান ফলাফল পর্যবেক্ষণ.
⇒ string
ফলাফল হল আপনার পাস করা স্ট্রিং, কারণ Aquarium T. তে কোনো সীমাবদ্ধতা রাখে না। String সহ যেকোনো ধরনের, পাস করা যেতে পারে।
-
genericsExample()এ, আরেকটিAquariumতৈরি করুন,waterSupplyজন্যnullপাস করুন।waterSupplyনাল হলে,"waterSupply is null"প্রিন্ট করুন।
fun genericsExample() {
val aquarium3 = Aquarium(null)
if (aquarium3.waterSupply == null) {
println("waterSupply is null")
}
}- আপনার প্রোগ্রাম চালান এবং ফলাফল পর্যবেক্ষণ.
⇒ waterSupply is null
Aquarium তৈরি করার সময় কেন আপনি null পাস করতে পারেন? এটি সম্ভব কারণ ডিফল্টরূপে, T এর অর্থ nullable Any? টাইপ, টাইপ অনুক্রমের শীর্ষে টাইপ। নিম্নলিখিতটি আপনি আগে টাইপ করেছেন তার সমতুল্য।
class Aquarium<T: Any?>(val waterSupply: T)- পাসিং
nullমঞ্জুরি না দেওয়ার জন্য, টাইপTএরAnyস্পষ্টভাবে, অপসারণ করে তৈরি করুন?Anyপরে.
class Aquarium<T: Any>(val waterSupply: T)এই পরিপ্রেক্ষিতে, Any একটি জেনেরিক সীমাবদ্ধতা বলা হয়। এর মানে T জন্য যেকোন প্রকার পাস করা যেতে পারে যতক্ষণ না এটি null না হয়।
- আপনি সত্যিই যা চান তা হল নিশ্চিত করা যে শুধুমাত্র একটি
WaterSupply(বা এর একটি সাবক্লাস)Tএর জন্য পাস করা যেতে পারে। আরও নির্দিষ্ট জেনেরিক সীমাবদ্ধতা সংজ্ঞায়িত করতেWaterSupplyসাথেAnyপ্রতিস্থাপন করুন।
class Aquarium<T: WaterSupply>(val waterSupply: T)ধাপ 4: আরও চেকিং যোগ করুন
এই ধাপে আপনি check() ফাংশন সম্পর্কে জানতে পারবেন যাতে আপনার কোড প্রত্যাশিতভাবে আচরণ করছে তা নিশ্চিত করতে সহায়তা করে। check() ফাংশনটি কোটলিনের একটি আদর্শ লাইব্রেরি ফাংশন। এটি একটি দাবী হিসাবে কাজ করে এবং একটি IllegalStateException নিক্ষেপ করবে যদি এর যুক্তিটি false বলে মূল্যায়ন করে।
- জল যোগ করতে
Aquariumক্লাসে একটিaddWater()পদ্ধতি যোগ করুন, একটিcheck()সহ যা নিশ্চিত করে যে আপনাকে প্রথমে জল প্রক্রিয়া করার প্রয়োজন নেই।
class Aquarium<T: WaterSupply>(val waterSupply: T) {
fun addWater() {
check(!waterSupply.needsProcessing) { "water supply needs processing first" }
println("adding water from $waterSupply")
}
}এই ক্ষেত্রে, needsProcessing সত্য হলে, check() একটি ব্যতিক্রম নিক্ষেপ করবে।
-
genericsExample()এ,LakeWaterদিয়ে একটিAquariumতৈরি করতে কোড যোগ করুন এবং তারপরে কিছু জল যোগ করুন।
fun genericsExample() {
val aquarium4 = Aquarium(LakeWater())
aquarium4.addWater()
}- আপনার প্রোগ্রাম চালান, এবং আপনি একটি ব্যতিক্রম পাবেন, কারণ জল প্রথমে ফিল্টার করা প্রয়োজন।
⇒ Exception in thread "main" java.lang.IllegalStateException: water supply needs processing first
at Aquarium.generics.Aquarium.addWater(Aquarium.kt:21)-
Aquariumজল যোগ করার আগে ফিল্টার করার জন্য একটি কল যোগ করুন। এখন আপনি যখন আপনার প্রোগ্রাম চালান, নিক্ষেপ করা কোন ব্যতিক্রম নেই।
fun genericsExample() {
val aquarium4 = Aquarium(LakeWater())
aquarium4.waterSupply.filter()
aquarium4.addWater()
}⇒ adding water from generics.LakeWater@880ec60
উপরের জেনেরিকের মৌলিক বিষয়গুলিকে কভার করে। নিম্নলিখিত কাজগুলি আরও কভার করে, তবে গুরুত্বপূর্ণ ধারণাটি হল কীভাবে একটি জেনেরিক সীমাবদ্ধতার সাথে একটি জেনেরিক ক্লাস ঘোষণা এবং ব্যবহার করা যায়।
এই টাস্কে, আপনি জেনেরিকের সাথে ইন এবং আউট প্রকার সম্পর্কে শিখবেন। একটি in টাইপ এমন একটি টাইপ যা শুধুমাত্র একটি ক্লাসে পাস করা যায়, ফেরত দেওয়া যায় না। একটি out টাইপ হল একটি টাইপ যা শুধুমাত্র একটি ক্লাস থেকে ফেরত দেওয়া যেতে পারে।
Aquarium ক্লাসটি দেখুন এবং আপনি দেখতে পাবেন যে সম্পত্তির waterSupply পাওয়ার সময় জেনেরিক টাইপটি ফেরত দেওয়া হয়। এমন কোন পদ্ধতি নেই যা একটি প্যারামিটার হিসাবে T টাইপের একটি মান নেয় (এটি কনস্ট্রাক্টরে সংজ্ঞায়িত করা ছাড়া)। কোটলিন আপনাকে ঠিক এই ক্ষেত্রে প্রকারগুলি out করতে দেয় এবং এটি কোথায় ব্যবহার করা নিরাপদ সে সম্পর্কে অতিরিক্ত তথ্য অনুমান করতে পারে। একইভাবে, আপনি জেনেরিক প্রকারের জন্য in সংজ্ঞায়িত করতে পারেন যেগুলি কেবলমাত্র পদ্ধতিতে পাস করা হয়, ফেরত দেওয়া হয় না। এটি কোড নিরাপত্তার জন্য কোটলিনকে অতিরিক্ত পরীক্ষা করার অনুমতি দেয়।
in এবং out প্রকারগুলি কোটলিনের টাইপ সিস্টেমের জন্য নির্দেশিকা। পুরো টাইপ সিস্টেমটি ব্যাখ্যা করা এই বুটক্যাম্পের সুযোগের বাইরে (এটি বেশ জড়িত); যাইহোক, কম্পাইলার এমন ধরনগুলিকে ফ্ল্যাগ করবে যেগুলি যথাযথভাবে মার্ক করা নেই in out , তাই আপনাকে সেগুলি সম্পর্কে জানতে হবে।
ধাপ 1: একটি আউট টাইপ সংজ্ঞায়িত করুন
-
Aquariumক্লাসে,T: WaterSupplyপরিবর্তন করুন একটিoutটাইপ।
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
...
}- একই ফাইলে, ক্লাসের বাইরে, একটি ফাংশন
addItemTo()ঘোষণা করুন যাWaterSupplyএকটিAquariumআশা করে।
fun addItemTo(aquarium: Aquarium<WaterSupply>) = println("item added")-
genericsExample()addItemTo()() কে কল করুন এবং আপনার প্রোগ্রাম চালান।
fun genericsExample() {
val aquarium = Aquarium(TapWater())
addItemTo(aquarium)
}⇒ item added
Kotlin নিশ্চিত করতে পারে যে addItemTo() জেনেরিক WaterSupply সাথে অনিরাপদ কিছু করবে না, কারণ এটি একটি out টাইপ হিসাবে ঘোষণা করা হয়েছে।
- আপনি যদি
outকীওয়ার্ডটি সরিয়ে দেন, তাহলেaddItemTo()কল করার সময় কম্পাইলার একটি ত্রুটি দেবে, কারণ Kotlin নিশ্চিত করতে পারে না যে আপনি টাইপের সাথে অনিরাপদ কিছু করছেন না।
ধাপ 2: একটি টাইপ সংজ্ঞায়িত করুন
in টাইপ out টাইপের অনুরূপ, তবে জেনেরিক প্রকারের জন্য যেগুলি শুধুমাত্র ফাংশনে পাস করা হয়, ফেরত দেওয়া হয় না। আপনি যদি একটি in ফেরত দেওয়ার চেষ্টা করেন তবে আপনি একটি কম্পাইলার ত্রুটি পাবেন। এই উদাহরণে আপনি একটি ইন্টারফেসের অংশ হিসাবে একটি in টাইপ সংজ্ঞায়িত করবেন।
- Aquarium.kt- এ, একটি ইন্টারফেস
Cleanerসংজ্ঞায়িত করুন যা একটি জেনেরিকTনেয় যাWaterSupplyজন্য সীমাবদ্ধ। যেহেতু এটি শুধুমাত্র একটি যুক্তি হিসাবে ব্যবহার করা হয়clean(), আপনি এটি একটিinপ্যারামিটার করতে পারেন।
interface Cleaner<in T: WaterSupply> {
fun clean(waterSupply: T)
}-
Cleanerইন্টারফেস ব্যবহার করতে, একটি ক্লাসTapWaterCleanerতৈরি করুন যা রাসায়নিক যোগ করেTapWaterপরিষ্কারের জন্যCleanerপ্রয়োগ করে।
class TapWaterCleaner : Cleaner<TapWater> {
override fun clean(waterSupply: TapWater) = waterSupply.addChemicalCleaners()
}-
Aquariumক্লাসে,TটাইপেরCleanerনিতেaddWater()আপডেট করুন এবং এটি যোগ করার আগে জল পরিষ্কার করুন।
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
fun addWater(cleaner: Cleaner<T>) {
if (waterSupply.needsProcessing) {
cleaner.clean(waterSupply)
}
println("water added")
}
}- একটি
TapWaterCleaner,TapWaterসহ একটিAquariumতৈরি করতেgenericsExample()উদাহরণ কোড আপডেট করুন এবং তারপর ক্লিনার ব্যবহার করে কিছু জল যোগ করুন। এটি প্রয়োজন অনুযায়ী ক্লিনার ব্যবহার করবে।
fun genericsExample() {
val cleaner = TapWaterCleaner()
val aquarium = Aquarium(TapWater())
aquarium.addWater(cleaner)
}আপনার কোড নিরাপদে জেনেরিক ব্যবহার করছে তা নিশ্চিত করতে Kotlin in এবং out ধরনের তথ্য ব্যবহার করবে। Out এবং in মনে রাখা সহজ: out প্রকারগুলি রিটার্ন মান হিসাবে বাইরের দিকে পাস করা যেতে পারে, in টাইপগুলি আর্গুমেন্ট হিসাবে ভিতরের দিকে পাস করা যেতে পারে।

আপনি যদি টাইপ এবং আউট টাইপের সমস্যা সমাধানের জন্য আরও খনন করতে চান তবে ডকুমেন্টেশনটি সেগুলিকে গভীরভাবে কভার করে।
এই টাস্কে আপনি জেনেরিক ফাংশন এবং কখন সেগুলি ব্যবহার করবেন তা শিখবেন। সাধারণত, একটি জেনেরিক ফাংশন তৈরি করা একটি ভাল ধারণা যখনই ফাংশনটি একটি জেনেরিক টাইপের একটি ক্লাসের আর্গুমেন্ট নেয়।
ধাপ 1: একটি জেনেরিক ফাংশন তৈরি করুন
- generics/Aquarium.kt- এ, একটি ফাংশন তৈরি করুন
isWaterClean()যা একটিAquariumনেয়। আপনাকে প্যারামিটারের জেনেরিক প্রকার উল্লেখ করতে হবে; একটি বিকল্প হলWaterSupplyব্যবহার করা।
fun isWaterClean(aquarium: Aquarium<WaterSupply>) {
println("aquarium water is clean: ${aquarium.waterSupply.needsProcessing}")
}কিন্তু এর মানে Aquarium কল করার জন্য একটি out টাইপ প্যারামিটার থাকতে হবে। কখনও কখনও out বা in খুব সীমাবদ্ধ কারণ আপনাকে ইনপুট এবং আউটপুট উভয়ের জন্য একটি টাইপ ব্যবহার করতে হবে। আপনি ফাংশন জেনেরিক করে out প্রয়োজনীয়তা অপসারণ করতে পারেন।
- ফাংশনটিকে জেনেরিক করার জন্য, একটি জেনেরিক টাইপ
Tএবং যেকোনো সীমাবদ্ধতার সাথে কীওয়ার্ডfunপরে কোণ বন্ধনী রাখুন, এই ক্ষেত্রে,WaterSupply।WaterSupplyপরিবর্তেTদ্বারা সীমাবদ্ধAquariumপরিবর্তন করুন।
fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) {
println("aquarium water is clean: ${!aquarium.waterSupply.needsProcessing}")
}T isWaterClean() এর একটি টাইপ প্যারামিটার যা অ্যাকোয়ারিয়ামের জেনেরিক প্রকার নির্দিষ্ট করতে ব্যবহৃত হচ্ছে। এই প্যাটার্নটি সত্যিই সাধারণ, এবং এটির মাধ্যমে কাজ করার জন্য কিছুক্ষণ সময় নেওয়া একটি ভাল ধারণা।
- ফাংশনের নামের ঠিক পরে এবং বন্ধনীর আগে কোণ বন্ধনীতে ধরনটি নির্দিষ্ট করে
isWaterClean()ফাংশনটিকে কল করুন।
fun genericsExample() {
val aquarium = Aquarium(TapWater())
isWaterClean<TapWater>(aquarium)
}- আর্গুমেন্ট
aquariumথেকে টাইপের অনুমানের কারণে, টাইপের প্রয়োজন নেই, তাই এটি সরিয়ে ফেলুন। আপনার প্রোগ্রাম চালান এবং আউটপুট পর্যবেক্ষণ.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
isWaterClean(aquarium)
}⇒ aquarium water is clean: false
ধাপ 2: রিফাইড টাইপ দিয়ে একটি জেনেরিক পদ্ধতি তৈরি করুন
আপনি পদ্ধতির জন্যও জেনেরিক ফাংশন ব্যবহার করতে পারেন, এমনকি তাদের নিজস্ব জেনেরিক ধরনের ক্লাসেও। এই ধাপে, আপনি Aquarium একটি জেনেরিক পদ্ধতি যোগ করুন যা এটিতে WaterSupply ধরন আছে কিনা তা পরীক্ষা করে।
-
Aquariumক্লাসে, একটি পদ্ধতি ঘোষণা করুন,hasWaterSupplyOfType()যেটি একটি জেনেরিক প্যারামিটারR(Tইতিমধ্যেই ব্যবহৃত হয়েছে) নেয়WaterSupplyসীমাবদ্ধ , এবং যদিwaterSupplyRটাইপের হয় তবেtrueফেরত দেয়। এটি আপনি আগে ঘোষিত ফাংশন মত, কিন্তুAquariumক্লাস ভিতরে.
fun <R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R- লক্ষ্য করুন যে চূড়ান্ত
Rলাল রঙে আন্ডারলাইন করা হয়েছে। এররটি কী তা দেখতে পয়েন্টারটি ধরে রাখুন।
- একটি
isকরার জন্য, আপনাকে Kotlin কে বলতে হবে যে টাইপটি reified বা বাস্তব, এবং ফাংশনে ব্যবহার করা যেতে পারে। এটি করার জন্য,funকীওয়ার্ডের সামনেinlineরাখুন এবং জেনেরিক টাইপRএর সামনেreified।
inline fun <reified R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R একবার একটি টাইপ রিফাইড হয়ে গেলে, আপনি এটিকে সাধারণ টাইপের মতো ব্যবহার করতে পারেন-কারণ ইনলাইন করার পরে এটি একটি বাস্তব প্রকার। তার মানে আপনি করতে পারেন টাইপ ব্যবহার করে is .
আপনি যদি এখানে reified ব্যবহার না করেন, তাহলে টাইপটি "বাস্তব" হবে না যাতে কোটলিন is অনুমতি দেয়। এর কারণ হল নন-রিফাইড টাইপগুলি শুধুমাত্র কম্পাইলের সময় উপলব্ধ, এবং আপনার প্রোগ্রাম দ্বারা রানটাইমে ব্যবহার করা যাবে না। এটি পরবর্তী বিভাগে আরও আলোচনা করা হয়েছে।
- টাইপ হিসাবে
TapWaterপাস করুন। জেনেরিক ফাংশন কল করার মতো, ফাংশনের নামের পরে টাইপ সহ কোণ বন্ধনী ব্যবহার করে জেনেরিক পদ্ধতিগুলিকে কল করুন। আপনার প্রোগ্রাম চালান এবং ফলাফল পর্যবেক্ষণ.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
println(aquarium.hasWaterSupplyOfType<TapWater>()) // true
}⇒ true
ধাপ 3: এক্সটেনশন ফাংশন করুন
আপনি নিয়মিত ফাংশন এবং এক্সটেনশন ফাংশনগুলির জন্যও রিফাইড টাইপ ব্যবহার করতে পারেন।
-
Aquariumক্লাসের বাইরে,WaterSupplyএisOfType()নামে একটি এক্সটেনশন ফাংশন সংজ্ঞায়িত করুন যা পরীক্ষা করে যে পাস করাWaterSupplyএকটি নির্দিষ্ট ধরনের, উদাহরণস্বরূপ,TapWater।
inline fun <reified T: WaterSupply> WaterSupply.isOfType() = this is T- মেথডের মত এক্সটেনশন ফাংশনকে কল করুন।
fun genericsExample() {
val aquarium = Aquarium(TapWater())
println(aquarium.waterSupply.isOfType<TapWater>())
}⇒ true
এই এক্সটেনশন ফাংশনগুলির সাথে, এটি কোন ধরণের Aquarium তা বিবেচ্য নয় ( Aquarium বা TowerTank বা অন্য কোনও উপশ্রেণী), যতক্ষণ না এটি একটি Aquarium । স্টার-প্রজেকশন সিনট্যাক্স ব্যবহার করা বিভিন্ন ধরনের মিল উল্লেখ করার একটি সুবিধাজনক উপায়। এবং যখন আপনি একটি তারকা-প্রক্ষেপণ ব্যবহার করেন, Kotlin নিশ্চিত করবে যে আপনিও অনিরাপদ কিছু করবেন না।
- একটি তারকা-প্রক্ষেপণ ব্যবহার করতে,
Aquariumপরে<*>রাখুন।hasWaterSupplyOfType()একটি এক্সটেনশন ফাংশন হিসাবে সরান, কারণ এটি আসলেAquariumমূল API এর অংশ নয়।
inline fun <reified R: WaterSupply> Aquarium<*>.hasWaterSupplyOfType() = waterSupply is R- কলটি
hasWaterSupplyOfType()এ পরিবর্তন করুন এবং আপনার প্রোগ্রামটি চালান।
fun genericsExample() {
val aquarium = Aquarium(TapWater())
println(aquarium.hasWaterSupplyOfType<TapWater>())
}⇒ true
আগের উদাহরণে, আপনাকে জেনেরিক টাইপটিকে reified হিসাবে চিহ্নিত করতে হবে এবং ফাংশনটিকে inline করতে হবে, কারণ কোটলিনকে রানটাইমে সেগুলি সম্পর্কে জানতে হবে, শুধু কম্পাইল সময় নয়।
সমস্ত জেনেরিক প্রকারগুলি শুধুমাত্র কোটলিন দ্বারা কম্পাইলের সময় ব্যবহৃত হয়। এটি কম্পাইলারকে নিশ্চিত করতে দেয় যে আপনি সবকিছু নিরাপদে করছেন। রানটাইম দ্বারা সমস্ত জেনেরিক প্রকার মুছে ফেলা হয়, তাই একটি মুছে ফেলা টাইপ চেক করার বিষয়ে আগের ত্রুটি বার্তা।
এটি দেখা যাচ্ছে যে কম্পাইলার রানটাইম পর্যন্ত জেনেরিক প্রকারগুলি না রেখে সঠিক কোড তৈরি করতে পারে। কিন্তু এর মানে এই যে কখনও কখনও আপনি কিছু করেন, is জেনেরিক ধরনের চেক, যে কম্পাইলার সমর্থন করতে পারে না। এই কারণেই কোটলিন রিফাইড বা বাস্তব প্রকার যোগ করেছে।
আপনি কোটলিন ডকুমেন্টেশনে রিফাইড প্রকার এবং টাইপ ইরেজার সম্পর্কে আরও পড়তে পারেন।
এই পাঠটি জেনেরিকের উপর দৃষ্টি নিবদ্ধ করে, যা কোডকে আরও নমনীয় এবং পুনরায় ব্যবহার করা সহজ করার জন্য গুরুত্বপূর্ণ।
- কোড আরও নমনীয় করতে জেনেরিক ক্লাস তৈরি করুন।
- জেনেরিকের সাথে ব্যবহৃত প্রকারগুলিকে সীমাবদ্ধ করতে জেনেরিক সীমাবদ্ধতা যুক্ত করুন।
- ক্লাসে পাস করা বা প্রত্যাবর্তন করা প্রকারগুলিকে সীমাবদ্ধ করতে আরও ভাল টাইপ চেকিং প্রদান করতে জেনেরিক সহ
inএবংoutপ্রকারগুলি ব্যবহার করুন৷ - জেনেরিক প্রকারের সাথে কাজ করার জন্য জেনেরিক ফাংশন এবং পদ্ধতি তৈরি করুন। যেমন:
fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) { ... } - একটি ক্লাসে নন-কোর কার্যকারিতা যোগ করতে জেনেরিক এক্সটেনশন ফাংশন ব্যবহার করুন।
- টাইপ ইরেজারের কারণে রিফাইড টাইপগুলি কখনও কখনও প্রয়োজনীয়। Reified প্রকারগুলি, জেনেরিক প্রকারের বিপরীতে, রানটাইম পর্যন্ত টিকে থাকে।
- আপনার কোড প্রত্যাশিতভাবে চলছে তা যাচাই করতে
check()ফাংশনটি ব্যবহার করুন। যেমন:
check(!waterSupply.needsProcessing) { "water supply needs processing first" }
কোটলিন ডকুমেন্টেশন
আপনি যদি এই কোর্সে কোনো বিষয়ে আরও তথ্য চান, বা আপনি যদি আটকে যান, https://kotlinlang.org আপনার সেরা শুরুর পয়েন্ট।
- জেনেরিক
- সাধারণ সীমাবদ্ধতা
- তারকা-অনুমান
-
Inএবংoutপ্রকার - পরিমার্জিত পরামিতি
- ইরেজার টাইপ করুন
-
check()ফাংশন
কোটলিন টিউটোরিয়াল
https://try.kotlinlang.org ওয়েবসাইটটিতে Kotlin Koans নামে সমৃদ্ধ টিউটোরিয়াল রয়েছে, একটি ওয়েব-ভিত্তিক দোভাষী , এবং উদাহরণ সহ রেফারেন্স ডকুমেন্টেশনের একটি সম্পূর্ণ সেট।
উদ্যতা কোর্স
এই বিষয়ে Udacity কোর্সটি দেখতে, প্রোগ্রামারদের জন্য Kotlin Bootcamp দেখুন।
ইন্টেলিজ আইডিয়া
IntelliJ IDEA-এর জন্য ডকুমেন্টেশন জেটব্রেইন্স ওয়েবসাইটে পাওয়া যাবে।
এই বিভাগে একজন প্রশিক্ষকের নেতৃত্বে একটি কোর্সের অংশ হিসাবে এই কোডল্যাবের মাধ্যমে কাজ করা শিক্ষার্থীদের জন্য সম্ভাব্য হোমওয়ার্ক অ্যাসাইনমেন্ট তালিকাভুক্ত করা হয়েছে। নিম্নলিখিতগুলি করা প্রশিক্ষকের উপর নির্ভর করে:
- প্রয়োজনে হোমওয়ার্ক বরাদ্দ করুন।
- শিক্ষার্থীদের সাথে যোগাযোগ করুন কিভাবে হোমওয়ার্ক অ্যাসাইনমেন্ট জমা দিতে হয়।
- হোমওয়ার্ক অ্যাসাইনমেন্ট গ্রেড.
প্রশিক্ষকরা এই পরামর্শগুলি যতটা কম বা যতটা চান ততটা ব্যবহার করতে পারেন, এবং তাদের উপযুক্ত মনে করে অন্য কোনও হোমওয়ার্ক বরাদ্দ করতে নির্দ্বিধায় করা উচিত।
আপনি যদি নিজে থেকে এই কোডল্যাবের মাধ্যমে কাজ করে থাকেন, তাহলে আপনার জ্ঞান পরীক্ষা করার জন্য এই হোমওয়ার্ক অ্যাসাইনমেন্টগুলিকে নির্দ্বিধায় ব্যবহার করুন৷
এই প্রশ্নগুলোর উত্তর দাও
প্রশ্ন 1
নিচের কোনটি জেনেরিক ধরনের নামকরণের নিয়ম?
▢ <Gen>
▢ <Generic>
▢ <T>
▢ <X>
প্রশ্ন 2
একটি জেনেরিক ধরনের জন্য অনুমোদিত ধরনের উপর একটি সীমাবদ্ধতা বলা হয়:
▢ একটি সাধারণ সীমাবদ্ধতা
▢ একটি সাধারণ সীমাবদ্ধতা
▢ দ্ব্যর্থতা নিরসন
▢ একটি সাধারণ প্রকারের সীমা
প্রশ্ন 3
রিফাইড মানে:
▢ একটি বস্তুর বাস্তব কার্য সম্পাদনের প্রভাব গণনা করা হয়েছে।
▢ ক্লাসে একটি সীমাবদ্ধ প্রবেশ সূচক সেট করা হয়েছে।
▢ জেনেরিক টাইপ প্যারামিটারটিকে একটি বাস্তব টাইপ করা হয়েছে।
▢ একটি দূরবর্তী ত্রুটি নির্দেশক ট্রিগার করা হয়েছে৷
পরবর্তী পাঠে এগিয়ে যান:
অন্যান্য কোডল্যাবগুলির লিঙ্ক সহ কোর্সের একটি ওভারভিউয়ের জন্য, "প্রোগ্রামারদের জন্য কোটলিন বুটক্যাম্প: কোর্সে স্বাগতম" দেখুন।