এই কোডল্যাবটি প্রোগ্রামারদের কোর্সের জন্য কোটলিন বুটক্যাম্পের অংশ। আপনি যদি কোডল্যাবগুলি ক্রমানুসারে কাজ করেন তবে আপনি এই কোর্সের সর্বাধিক মূল্য পাবেন৷ আপনার জ্ঞানের উপর নির্ভর করে, আপনি কিছু বিভাগ স্কিম করতে সক্ষম হতে পারেন। এই কোর্সটি এমন প্রোগ্রামারদের জন্য তৈরি যারা একটি অবজেক্ট-ওরিয়েন্টেড ভাষা জানেন এবং কোটলিন শিখতে চান।
ভূমিকা
এই কোডল্যাবে আপনাকে জেনেরিক ক্লাস, ফাংশন এবং পদ্ধতি এবং তারা কোটলিনে কীভাবে কাজ করে তার সাথে পরিচয় করিয়ে দেওয়া হয়েছে।
একটি একক নমুনা অ্যাপ তৈরি করার পরিবর্তে, এই কোর্সের পাঠগুলি আপনার জ্ঞান তৈরি করার জন্য ডিজাইন করা হয়েছে, তবে একে অপরের থেকে আধা-স্বতন্ত্র থাকুন যাতে আপনি আপনার পরিচিত বিভাগগুলিকে স্কিম করতে পারেন। তাদের একসাথে বাঁধতে, অনেক উদাহরণ একটি অ্যাকোয়ারিয়াম থিম ব্যবহার করে। এবং আপনি যদি সম্পূর্ণ অ্যাকোয়ারিয়ামের গল্প দেখতে চান, তাহলে প্রোগ্রামারদের জন্য কোটলিন বুটক্যাম্প উদাসিটি কোর্সটি দেখুন।
আপনি ইতিমধ্যে কি জানা উচিত
- কোটলিন ফাংশন, ক্লাস এবং পদ্ধতির সিনট্যাক্স
- কিভাবে 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
প্রসারিত করে, এবং প্রয়োজন প্রক্রিয়াকরণের জন্যtrue
পাস করে, কারণ কলের জলেneedsProcessing
থাকে যা মাছের জন্য খারাপ। -
TapWater
এ,addChemicalCleaners()
নামক একটি ফাংশন সংজ্ঞায়িত করুন যা জল পরিষ্কার করার পরেneedsProcessing
কেfalse
সেট করে।needsProcessing
সম্পত্তিTapWater
থেকে সেট করা যেতে পারে, কারণ এটি ডিফল্টরূপেpublic
এবং সাবক্লাসে অ্যাক্সেসযোগ্য। এখানে সম্পূর্ণ কোড আছে.
package generics
open class WaterSupply(var needsProcessing: Boolean)
class TapWater : WaterSupply(true) {
fun addChemicalCleaners() {
needsProcessing = false
}
}
-
FishStoreWater
এবংWaterSupply
নামে জলLakeWater
আরও দুটি উপশ্রেণী তৈরি করুন।FishStoreWater
প্রক্রিয়াকরণের প্রয়োজন নেই, তবেLakeWater
filter()
পদ্ধতিতে ফিল্টার করতে হবে। ফিল্টার করার পরে, এটিকে আবার প্রসেস করার দরকার নেই, তাইfilter()
এ,needsProcessing = false
সেট করুন।
class FishStoreWater : WaterSupply(false)
class LakeWater : WaterSupply(true) {
fun filter() {
needsProcessing = false
}
}
আপনার যদি অতিরিক্ত তথ্যের প্রয়োজন হয়, কোটলিনে উত্তরাধিকার সম্পর্কিত পূর্ববর্তী পাঠটি পর্যালোচনা করুন।
ধাপ 2: একটি জেনেরিক ক্লাস তৈরি করুন
এই ধাপে আপনি বিভিন্ন ধরনের জল সরবরাহ সমর্থন করার জন্য Aquarium
শ্রেণী পরিবর্তন করেন।
- Aquarium.kt- এ, ক্লাসের নামের পরে বন্ধনীতে
<T>
সহ একটিAquarium
ক্লাস সংজ্ঞায়িত করুন। -
Aquarium
T
টাইপের একটি অপরিবর্তনীয় সম্পত্তিwaterSupply
যোগ করুন।
class Aquarium<T>(val waterSupply: T)
-
genericsExample()
নামে একটি ফাংশন লিখুন। এটি একটি ক্লাসের অংশ নয়, তাই এটি ফাইলের শীর্ষ স্তরে যেতে পারে, যেমনmain()
ফাংশন বা ক্লাস সংজ্ঞা। ফাংশনে, একটিAquarium
তৈরি করুন এবং এটিকে একটিWaterSupply
। যেহেতুwaterSupply
প্যারামিটারটি জেনেরিক, তাই আপনাকে অবশ্যই কোণ বন্ধনীতে ধরনটি উল্লেখ করতে হবে<>
।
fun genericsExample() {
val aquarium = Aquarium<TapWater>(TapWater())
}
-
waterSupply
genericsExample()
এ আপনার কোড অ্যাকোয়ারিয়ামের জল সরবরাহ অ্যাক্সেস করতে পারে। কারণ এটি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()
}
- কি ঘটছে তা দেখতে,
needsProcessing
addChemicalCleaners()
কল করার আগে এবং পরে প্রিন্টের প্রয়োজন প্রসেসিং। নীচে সম্পন্ন ফাংশন আছে.
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
শ্রেণীকে আরও সুনির্দিষ্ট করে তোলেন যে আপনি এতে কী রাখতে পারেন।
-
waterSupply
genericsExample()
-এ, একটিAquarium
তৈরি করুন, জল সরবরাহের জন্য একটি স্ট্রিং পাস করুন, তারপর অ্যাকোয়ারিয়ামেরwaterSupply
সম্পত্তি প্রিন্ট করুন৷
fun genericsExample() {
val aquarium2 = Aquarium("string")
println(aquarium2.waterSupply)
}
- আপনার প্রোগ্রাম চালান ফলাফল পর্যবেক্ষণ.
⇒ string
ফলাফল হল আপনার পাস করা স্ট্রিং, কারণ Aquarium
T.
-তে কোনো সীমাবদ্ধতা রাখে না। String
সহ যেকোনো ধরনের, পাস করা যেতে পারে।
-
waterSupply
genericsExample()
এ, আরেকটিAquarium
তৈরি করুন, জল সরবরাহের জন্য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")
-
addItemTo()
থেকেgenericsExample()
() কে কল করুন এবং আপনার প্রোগ্রাম চালান।
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
তৈরি করতে genericsExamplegenericsExample()
উদাহরণ কোড আপডেট করুন এবং তারপর ক্লিনার ব্যবহার করে কিছু জল যোগ করুন। এটি প্রয়োজন অনুযায়ী ক্লিনার ব্যবহার করবে।
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
সীমাবদ্ধ , এবং যদিwaterSupply
R
টাইপের হয় তবে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
রিফাইড মানে:
▢ একটি বস্তুর বাস্তব কার্য সম্পাদনের প্রভাব গণনা করা হয়েছে।
▢ ক্লাসে একটি সীমাবদ্ধ প্রবেশ সূচক সেট করা হয়েছে।
▢ জেনেরিক টাইপ প্যারামিটারটিকে একটি বাস্তব টাইপ করা হয়েছে।
▢ একটি দূরবর্তী ত্রুটি নির্দেশক ট্রিগার করা হয়েছে৷
পরবর্তী পাঠে এগিয়ে যান:
অন্যান্য কোডল্যাবগুলির লিঙ্ক সহ কোর্সের একটি ওভারভিউয়ের জন্য, "প্রোগ্রামারদের জন্য কোটলিন বুটক্যাম্প: কোর্সে স্বাগতম" দেখুন।