Kotlin এর Generics এবং Variance
কটলিনে Generics এবং Variance হলো দুটি গুরুত্বপূর্ণ ফিচার যা টাইপ সেফটি এবং কোড পুনঃব্যবহারযোগ্যতা বাড়াতে সাহায্য করে। Generics ব্যবহার করে আপনি ক্লাস, ফাংশন, এবং ইন্টারফেসে টাইপ প্যারামিটার যুক্ত করতে পারেন। Variance টাইপের সম্পর্কের মাধ্যমে একটি ক্লাসের বা ইন্টারফেসের সদস্যদেরকে নিরাপদভাবে পরিচালনা করতে সক্ষম করে। নিচে Generics এবং Variance নিয়ে বিস্তারিত আলোচনা করা হলো:
১. Generics
Generics কটলিনে এমন একটি ফিচার যা আপনাকে ক্লাস, ফাংশন এবং ইন্টারফেসে টাইপ প্যারামিটার ব্যবহার করতে দেয়। এটি টাইপ সেফটি নিশ্চিত করে এবং একই কোডে বিভিন্ন টাইপের ডেটা পরিচালনা করতে সহায়তা করে।
i) Generic Class
একটি Generic Class তৈরি করতে, আপনাকে ক্লাসের নামের পাশে টাইপ প্যারামিটার ব্যবহার করতে হবে।
উদাহরণ:
class Box<T>(val item: T) {
fun getItem(): T {
return item
}
}
fun main() {
val intBox = Box(123)
val stringBox = Box("Hello")
println(intBox.getItem()) // আউটপুট: 123
println(stringBox.getItem()) // আউটপুট: Hello
}
ব্যাখ্যা:
- এখানে
Boxএকটি Generic Class, যাTটাইপ প্যারামিটার গ্রহণ করে। এটি বিভিন্ন টাইপের ডেটা ধারণ করতে সক্ষম।
ii) Generic Function
আপনি ফাংশনেও Generics ব্যবহার করতে পারেন।
উদাহরণ:
kotlin
Copy code
fun <T> printItem(item: T) {
println(item)
}
fun main() {
printItem(42) // আউটপুট: 42
printItem("Kotlin") // আউটপুট: Kotlin
}
ব্যাখ্যা:
- এখানে
printItemএকটি Generic Function, যা যেকোনো টাইপের ডেটা প্রিন্ট করতে সক্ষম।
২. Variance
Variance কটলিনে টাইপের সম্পর্ক বোঝাতে ব্যবহৃত হয়, যা কোডের টাইপ সেফটি বাড়ায়। Variance মূলত দুই প্রকার: Covariance এবং Contravariance।
i) Covariance
Covariance টাইপের জন্য out কিওয়ার্ড ব্যবহার করে ডিফাইন করা হয়। এটি নির্দেশ করে যে একটি ক্লাসের বা ইন্টারফেসের সদস্যগুলি আউটপুট হিসেবে কাজ করতে পারে।
উদাহরণ:
interface Producer<out T> {
fun produce(): T
}
class StringProducer : Producer<String> {
override fun produce(): String {
return "Hello"
}
}
fun main() {
val producer: Producer<Any> = StringProducer()
println(producer.produce()) // আউটপুট: Hello
}
ব্যাখ্যা:
- এখানে
Producerএকটি Covariant টাইপ প্যারামিটার ব্যবহার করছে, যাoutকিওয়ার্ডের মাধ্যমে নির্দেশ করা হয়েছে। এর ফলেProducer<String>কেProducer<Any>হিসাবে ব্যবহার করা যেতে পারে।
ii) Contravariance
Contravariance টাইপের জন্য in কিওয়ার্ড ব্যবহার করে ডিফাইন করা হয়। এটি নির্দেশ করে যে একটি ক্লাসের বা ইন্টারফেসের সদস্যগুলি ইনপুট হিসেবে কাজ করতে পারে।
উদাহরণ:
interface Consumer<in T> {
fun consume(item: T)
}
class StringConsumer : Consumer<String> {
override fun consume(item: String) {
println("Consuming: $item")
}
}
fun main() {
val consumer: Consumer<Any> = StringConsumer()
consumer.consume("Kotlin") // আউটপুট: Consuming: Kotlin
}
ব্যাখ্যা:
- এখানে
Consumerএকটি Contravariant টাইপ প্যারামিটার ব্যবহার করছে, যাinকিওয়ার্ডের মাধ্যমে নির্দেশ করা হয়েছে। এর ফলেConsumer<String>কেConsumer<Any>হিসাবে ব্যবহার করা যেতে পারে।
উপসংহার
কটলিনের Generics এবং Variance টাইপ সেফটি এবং কোডের পুনঃব্যবহারযোগ্যতা বাড়াতে গুরুত্বপূর্ণ ভূমিকা পালন করে। Generics আপনাকে টাইপ প্যারামিটার ব্যবহার করে ক্লাস এবং ফাংশন তৈরি করতে সক্ষম করে, যেখানে Variance টাইপের সম্পর্ক বোঝাতে সাহায্য করে। Covariance এবং Contravariance এর মাধ্যমে আপনি আরও নিরাপদ এবং কার্যকরী কোড লিখতে পারবেন।
Generics কী এবং কিভাবে কাজ করে
Generics হলো একটি শক্তিশালী ফিচার যা কটলিনসহ অনেক প্রোগ্রামিং ভাষায় ব্যবহৃত হয়। এটি একটি ক্লাস, ইন্টারফেস, বা ফাংশনে টাইপ প্যারামিটার ব্যবহার করে, যাতে একই কোড বিভিন্ন ডেটা টাইপের সাথে কাজ করতে পারে। Generics কোডের পুনঃব্যবহারযোগ্যতা বৃদ্ধি করে এবং টাইপ সেফটি নিশ্চিত করে। নিচে Generics-এর ব্যাখ্যা, সুবিধা এবং কিভাবে কাজ করে তা বিস্তারিতভাবে আলোচনা করা হলো।
১. Generics কী?
Generics হল টাইপ প্যারামিটার ব্যবহার করে কোড লেখার একটি পদ্ধতি। এটি বিশেষভাবে প্রয়োগ করা হয় যখন আপনি একটি ফাংশন বা ডেটা স্ট্রাকচার তৈরি করছেন যা বিভিন্ন টাইপের ডেটার সাথে কাজ করতে পারে।
উদাহরণ:
class Box<T>(var item: T) {
fun getItem(): T {
return item
}
}
fun main() {
val intBox = Box(123)
println(intBox.getItem()) // আউটপুট: 123
val stringBox = Box("Hello, Kotlin!")
println(stringBox.getItem()) // আউটপুট: Hello, Kotlin!
}
ব্যাখ্যা:
- এখানে
Boxক্লাসটি একটি টাইপ প্যারামিটারTগ্রহণ করে, যাitemপ্রপার্টির টাইপ হতে পারে।Boxক্লাসের বিভিন্ন ইনস্ট্যান্স তৈরি করা হয়েছেIntএবংStringটাইপের জন্য।
২. Generics এর সুবিধা
i) Type Safety
Generics কোডে টাইপ নিরাপত্তা নিশ্চিত করে, কারণ এটি রানটাইমে টাইপ সম্পর্কিত সমস্যা কমায়।
fun <T> printList(items: List<T>) {
for (item in items) {
println(item)
}
}
ব্যাখ্যা:
- এখানে
printListএকটি generic ফাংশন, যা যে কোনো টাইপের লিস্ট গ্রহণ করে।
ii) Code Reusability
Generics ব্যবহার করে একটি ফাংশন বা ক্লাস একাধিক টাইপের সাথে কাজ করতে পারে, যা কোডের পুনঃব্যবহারযোগ্যতা বাড়ায়।
iii) Elimination of Type Casting
Generics ব্যবহার করে টাইপ কাস্টিংয়ের প্রয়োজনীয়তা কমে যায়।
val stringList: List<String> = listOf("A", "B", "C")
// কোন কাস্টিংয়ের প্রয়োজন নেই
৩. Variance in Generics
Generics-এ variance টাইপ প্যারামিটারগুলোর ইনহেরিটেন্স সম্পর্কিত। এটি প্রধানত তিন ধরনের:
i) Covariance (out)
Covariance আপনাকে একটি টাইপ প্যারামিটারকে এমনভাবে ব্যবহার করতে দেয় যাতে আপনি সাবটাইপগুলি ব্যবহার করতে পারেন।
class Box<out T>(val item: T)
fun main() {
val box: Box<Number> = Box(123) // Covariance allows this
val intBox: Box<Int> = box // Box<Int> can be assigned from Box<Number>
}
ব্যাখ্যা:
- এখানে
Box<out T>ব্যবহার করা হয়েছে, যা নির্দেশ করে যেTটাইপ কেবল আউটপুট হিসাবে ব্যবহৃত হবে।
ii) Contravariance (in)
Contravariance আপনাকে টাইপ প্যারামিটারকে ইনপুট হিসাবে ব্যবহার করতে দেয়, যাতে আপনি সুপারটাইপগুলি ব্যবহার করতে পারেন।
class Printer<in T> {
fun print(item: T) {
println(item)
}
}
fun main() {
val printer: Printer<Any> = Printer<Int>() // Printer<Int> can be assigned to Printer<Any>
printer.print(123)
}
ব্যাখ্যা:
- এখানে
Printer<in T>ব্যবহার করা হয়েছে, যা নির্দেশ করে যেTটাইপ কেবল ইনপুট হিসাবে ব্যবহৃত হবে।
iii) Non-variance (No Keyword)
Non-variance হলো যখন আপনি টাইপ প্যারামিটারকে neither in nor out হিসাবে ঘোষণা করেন। এটি টাইপ নিরাপত্তা বাড়ায়।
৪. Constraints on Generics
কখনও কখনও, আপনি চান যে একটি টাইপ প্যারামিটার অবশ্যই একটি নির্দিষ্ট ক্লাস বা ইন্টারফেসের সাবটাইপ হতে হবে। এটি করতে, আপনি where কিওয়ার্ড ব্যবহার করতে পারেন।
fun <T> printIfNotNull(item: T?) where T : Any {
item?.let { println(it) }
}
ব্যাখ্যা:
- এখানে
T : Anyনির্দেশ করে যেTঅবশ্যইAnyটাইপের সাবটাইপ হতে হবে।
উপসংহার
Generics কটলিনের একটি শক্তিশালী ফিচার, যা কোডের পুনঃব্যবহারযোগ্যতা, টাইপ নিরাপত্তা এবং কার্যকারিতা বাড়ায়। এটি আপনাকে বিভিন্ন টাইপের ডেটার সাথে কাজ করতে দেয়, যা প্রোগ্রামিংকে আরও কার্যকর এবং সংগঠিত করে তোলে।
Variance (In, Out, এবং No Variance)
কটলিনে Variance হলো একটি ধারণা যা জেনেরিক টাইপগুলোর মধ্যে সম্পর্ক প্রতিষ্ঠা করে। Variance ব্যবহারের মাধ্যমে আপনি কোডকে আরও নিরাপদ ও পুনঃব্যবহারযোগ্য করতে পারেন। কটলিনে প্রধানত তিন ধরনের Variance আছে: Invariance, Covariance, এবং Contravariance। নিচে এই ধারণাগুলো নিয়ে বিস্তারিত আলোচনা করা হলো।
১. Invariance
Invariance হলো একটি স্ট্যান্ডার্ড পরিস্থিতি যেখানে আপনি জেনেরিক টাইপের সঠিক টাইপ নির্ধারণ করতে হবে। যদি একটি টাইপ List<Dog> হয়, তাহলে List<Animal> হতে পারবে না, এমনকি যদি Dog Animal এর একটি সাবটাইপও হয়।
উদাহরণ:
class Box<T>(val item: T)
fun main() {
val box1: Box<Animal> = Box(Dog()) // এটি সম্ভব
// val box2: Box<Dog> = box1 // এটি সম্ভব নয়
}
ব্যাখ্যা:
- এখানে
Box<T>এর ইনস্ট্যান্সেAnimalএবংDogআলাদা টাইপ হওয়ায় এটি ইনভারিয়েন্স।Box<Dog>কেBox<Animal>হিসেবে ব্যবহার করা যাবে না।
২. Covariance (Out)
Covariance ব্যবহার করে আপনি টাইপ প্যারামিটারকে out হিসাবে চিহ্নিত করতে পারেন, যা টাইপ হায়ারার্কিতে সাবটাইপকে অনুমতি দেয়। অর্থাৎ, আপনি একটি জেনেরিক টাইপের সাথে শুধুমাত্র রিটার্ন টাইপ হিসাবে কাজ করতে পারবেন।
উদাহরণ:
class Box<out T>(val item: T)
fun main() {
val dogBox: Box<Dog> = Box(Dog())
val animalBox: Box<Animal> = dogBox // এটি সম্ভব
}
ব্যাখ্যা:
- এখানে
Box<out T>এর মাধ্যমেTটাইপের সাথে Covariance প্রকাশ করা হয়েছে।Box<Dog>থেকেBox<Animal>এ রূপান্তর সম্ভব।
৩. Contravariance (In)
Contravariance ব্যবহার করে আপনি টাইপ প্যারামিটারকে in হিসাবে চিহ্নিত করতে পারেন, যা টাইপ হায়ারার্কিতে সুপারটাইপের অনুমতি দেয়। অর্থাৎ, আপনি একটি জেনেরিক টাইপের সাথে শুধুমাত্র ইনপুট টাইপ হিসেবে কাজ করতে পারবেন।
উদাহরণ:
class Box<in T> {
fun add(item: T) {
// কোড যা আইটেম যুক্ত করে
}
}
fun main() {
val box: Box<Animal> = Box()
box.add(Dog()) // এটি সম্ভব, কারণ Dog হল Animal এর সাবটাইপ
}
ব্যাখ্যা:
- এখানে
Box<in T>এর মাধ্যমেTটাইপের সাথে Contravariance প্রকাশ করা হয়েছে।Box<Animal>কেBox<Dog>এর ইনপুট হিসেবে ব্যবহার করা যায়।
৪. No Variance
No Variance হলো এমন পরিস্থিতি যেখানে টাইপ প্যারামিটার কেবলমাত্র এক ধরনের কাজে ব্যবহৃত হয় এবং এতে কোনো Variance নেই। এটি একটি সাধারণ জেনেরিক টাইপ যেখানে Covariance বা Contravariance উভয়ই নেই।
উদাহরণ:
class Box<T>(val item: T)
fun main() {
val box: Box<Dog> = Box(Dog())
// box.item = Animal() // এটি সম্ভব নয়
}
ব্যাখ্যা:
- এখানে
Box<T>একটি সাধারণ জেনেরিক ক্লাস, যেখানে কোনো Variance নেই।itemএর টাইপ নির্দিষ্ট করা হয়েছে, তাই এটি ইনভারিয়েন্ট।
উপসংহার
কটলিনে Variance টাইপ সেফটি নিশ্চিত করতে এবং জেনেরিক টাইপগুলোর মধ্যে সম্পর্ক স্থাপন করতে সাহায্য করে। Covariance (out) এবং Contravariance (in) এর মাধ্যমে আপনি টাইপের হায়ারার্কি ব্যবহার করে কোডকে আরও ফ্লেক্সিবল করতে পারেন, আর Invariance সাধারণ ব্যবহার নিশ্চিত করে।
Type Constraints এবং Generic Functions
কটলিনের Type Constraints এবং Generic Functions আপনাকে টাইপ নিরাপত্তা বজায় রেখে ফাংশন এবং ক্লাস তৈরি করতে সক্ষম করে। Type Constraints ব্যবহার করে আপনি Generic Types এর উপর নিয়ন্ত্রণ পেতে পারেন, যা নিশ্চিত করে যে একটি নির্দিষ্ট টাইপের অবজেক্ট কেবল নির্দিষ্ট শর্তে ব্যবহার করা হবে। নিচে Type Constraints এবং Generic Functions নিয়ে বিস্তারিত আলোচনা করা হলো:
১. Type Constraints
Type Constraints আপনাকে টাইপ প্যারামিটারগুলির উপর শর্ত আরোপ করতে দেয়। আপনি একটি Generic ক্লাস বা ফাংশনে where ক্লজ ব্যবহার করে টাইপের উপর নিয়ন্ত্রণ আরোপ করতে পারেন।
i) Type Constraint Syntax
fun <T> functionName(param: T) where T : SomeClass
ii) উদাহরণ
Type Constraints সহ Generic Function:
open class Animal {
fun makeSound() = "Some sound"
}
class Dog : Animal() {
fun fetch() = "Fetching..."
}
fun <T> callAnimalSound(animal: T) where T : Animal {
println(animal.makeSound())
}
fun main() {
val dog = Dog()
callAnimalSound(dog) // আউটপুট: Some sound
}
ব্যাখ্যা:
- এখানে
callAnimalSoundএকটি Generic Function যাTটাইপ প্যারামিটার গ্রহণ করে।where T : Animalদিয়ে টাইপের উপর শর্ত আরোপ করা হয়েছে, যাতে কেবলAnimalবা তার সাবক্লাস ব্যবহার করা যায়।
২. Generic Functions
Generic Functions হলো এমন ফাংশন যা একটি বা একাধিক টাইপ প্যারামিটার গ্রহণ করে। এটি কোড পুনঃব্যবহারযোগ্যতা বাড়াতে এবং টাইপ নিরাপত্তা নিশ্চিত করতে সাহায্য করে।
i) Generic Function Syntax
fun <T> functionName(param: T): ReturnType {
// Function body
}
ii) উদাহরণ
একটি Generic Function:
fun <T> printList(items: List<T>) {
for (item in items) {
println(item)
}
}
fun main() {
val intList = listOf(1, 2, 3)
val stringList = listOf("Kotlin", "Java", "Python")
printList(intList) // আউটপুট: 1 2 3
printList(stringList) // আউটপুট: Kotlin Java Python
}
ব্যাখ্যা:
- এখানে
printListএকটি Generic Function যাList<T>গ্রহণ করে এবং প্রতিটি আইটেম প্রিন্ট করে। এটি যে কোন টাইপের List প্রক্রিয়া করতে সক্ষম।
৩. Multiple Type Constraints
আপনি একাধিক টাইপ কনস্ট্রেইন্টও যুক্ত করতে পারেন। এটি where ক্লজের মাধ্যমে করা হয়।
i) উদাহরণ
interface Comparable<T> {
fun compareTo(other: T): Int
}
fun <T> sortList(items: List<T>) where T : Comparable<T> {
// Sorting logic (for example purpose, just printing)
println("Sorting list of items")
}
fun main() {
// sortList(listOf(1, 2, 3)) // This would work if we had implemented sorting
}
ব্যাখ্যা:
- এখানে
sortListফাংশনে টাইপ প্যারামিটারTএর উপরComparable<T>টাইপ কনস্ট্রেইন্ট প্রয়োগ করা হয়েছে, যাতেTঅবশ্যইComparableইন্টারফেসের একটি বাস্তবায়ন হতে হবে।
৪. Generic Classes with Constraints
আপনি Generic ক্লাসেও Type Constraints ব্যবহার করতে পারেন।
i) উদাহরণ
class Box<T>(val item: T) where T : Comparable<T> {
fun isGreaterThan(other: T): Boolean {
return item > other
}
}
fun main() {
val box1 = Box(5)
val box2 = Box(3)
println(box1.isGreaterThan(box2.item)) // আউটপুট: true
}
ব্যাখ্যা:
- এখানে
Boxএকটি Generic ক্লাস যাTটাইপ প্যারামিটার গ্রহণ করে এবংwhere T : Comparable<T>কনস্ট্রেইন্ট ব্যবহার করেছে, যাতেTঅবশ্যইComparableহতে হবে।
উপসংহার
কটলিনের Type Constraints এবং Generic Functions আপনাকে টাইপ নিরাপত্তা বজায় রেখে ক্লাস এবং ফাংশন তৈরি করার ক্ষমতা প্রদান করে। Type Constraints ব্যবহার করে আপনি নির্দিষ্ট টাইপের উপর নিয়ন্ত্রণ আরোপ করতে পারেন, এবং Generic Functions কোডের পুনঃব্যবহারযোগ্যতা এবং কার্যকারিতা বাড়ায়।
Reified Types এবং Inline Functions
Reified Types এবং Inline Functions কটলিনের দুইটি শক্তিশালী ফিচার, যা ফাংশনাল প্রোগ্রামিং এবং টাইপ সেফটি উন্নত করতে সহায়ক। এই ফিচারগুলো কিভাবে কাজ করে এবং কেন এগুলো ব্যবহার করা হয় তা নিচে বিস্তারিতভাবে আলোচনা করা হলো।
১. Inline Functions
Inline Functions হলো এমন ফাংশন যেগুলোকে কম্পাইলার দ্বারা কল করার সময় বাস্তবায়িত (substituted) করা হয়, অর্থাৎ ফাংশনের শরীরকে কল করার স্থানে প্রতিস্থাপন করা হয়। এটি ফাংশন কলের সময় ওভারহেড কমায় এবং প্রোগ্রামের পারফরম্যান্স বাড়ায়।
i) Inline Functions এর Syntax
inline fun functionName(parameters) {
// Function body
}
উদাহরণ:
inline fun inlineFunction(block: () -> Unit) {
println("Before executing the block")
block() // Block will be executed here
println("After executing the block")
}
fun main() {
inlineFunction {
println("This is the inline function block.")
}
}
ব্যাখ্যা:
- এখানে
inlineFunctionএকটি inline function, যা একটি ব্লক প্যারামিটার গ্রহণ করে। যখন এটি কল করা হয়, তখন ব্লকটি সরাসরি ফাংশনের শরীরে প্রতিস্থাপন করা হয়।
ii) Benefits of Inline Functions
- Performance Improvement: Inline functions ব্যবহারে ফাংশন কলের ওভারহেড কমে যায়।
- Higher-Order Functions: Inline functions Higher-order functions এর সাথে ব্যবহারে কার্যকরী হয় এবং lambda expressions এর উপাদানগুলোর সময়সীমা উন্নত করে।
২. Reified Types
Reified Types হলো একটি কনসেপ্ট যা টাইপ প্যারামিটারকে runtime এ উপলব্ধ করতে সক্ষম করে। সাধারণত, generic types runtime এ erasure হয়, কিন্তু reified কিওয়ার্ড ব্যবহার করলে এটি সম্ভব হয়।
i) Reified Types এর Syntax
Reified types ব্যবহার করতে হলে, inline function এর সাথে reified কিওয়ার্ড ব্যবহার করতে হয়।
inline fun <reified T> typeCheck(value: Any) {
if (value is T) {
println("Value is of type ${T::class.simpleName}")
} else {
println("Value is not of type ${T::class.simpleName}")
}
}
উদাহরণ:
inline fun <reified T> typeCheck(value: Any) {
if (value is T) {
println("Value is of type ${T::class.simpleName}")
} else {
println("Value is not of type ${T::class.simpleName}")
}
}
fun main() {
typeCheck<String>("Hello") // আউটপুট: Value is of type String
typeCheck<Int>(123) // আউটপুট: Value is of type Int
typeCheck<Double>(123.45) // আউটপুট: Value is not of type Int
}
ব্যাখ্যা:
- এখানে
typeCheckএকটি inline function যাreified Tটাইপ প্যারামিটার গ্রহণ করে। এটি runtime এTটাইপের উপর ভিত্তি করে টাইপ চেক করতে সক্ষম।
ii) Benefits of Reified Types
- Type Safety: Reified types ব্যবহার করে টাইপ সেফটি নিশ্চিত করা যায়, কারণ আপনি runtime এ টাইপ চেক করতে পারেন।
- Cleaner Code: Reified types কোডকে আরো পরিষ্কার এবং সংক্ষিপ্ত করে, কারণ আপনি টাইপ চেক করতে টাইপ কাস্টিংয়ের প্রয়োজন হয় না।
৩. Inline Functions with Reified Types
একটি inline function এবং reified type একসাথে ব্যবহার করে, আপনি উচ্চতর কার্যকারিতা অর্জন করতে পারেন। উদাহরণস্বরূপ, একটি generic ফাংশন তৈরি করতে পারেন যা runtime এ টাইপ চেকিং করতে সক্ষম।
inline fun <reified T> List<*>.filterIsInstance(): List<T> {
return this.filterIsInstance<T>()
}
fun main() {
val mixedList: List<Any> = listOf("Kotlin", 42, 3.14)
val strings: List<String> = mixedList.filterIsInstance<String>()
println(strings) // আউটপুট: [Kotlin]
}
ব্যাখ্যা:
- এখানে
filterIsInstanceএকটি inline function যা reified type ব্যবহার করে একটি লিস্ট থেকে নির্দিষ্ট টাইপের অবজেক্টগুলোকে ফিল্টার করতে সক্ষম।
উপসংহার
Inline Functions এবং Reified Types কটলিনের শক্তিশালী ফিচার, যা কোডের কার্যকারিতা, রিডেবিলিটি এবং টাইপ সেফটি বাড়ায়। Inline functions ফাংশন কলের ওভারহেড কমায় এবং reified types runtime এ টাইপ চেকিংয়ের ক্ষমতা প্রদান করে।
Read more