1. স্বাগতম!
এই কোডল্যাবে, আপনি শিখবেন কিভাবে আপনার কোডকে জাভা থেকে কোটলিনে রূপান্তর করতে হয়। আপনি শিখবেন কোটলিন ভাষা নিয়মাবলী কী এবং কীভাবে নিশ্চিত করবেন যে আপনি যে কোডটি লিখছেন তা সেগুলি অনুসরণ করে।
এই কোডল্যাবটি জাভা ব্যবহারকারী যেকোনো ডেভেলপারের জন্য উপযুক্ত যারা তাদের প্রকল্প কোটলিনে স্থানান্তর করার কথা ভাবছেন। আমরা কয়েকটি জাভা ক্লাস দিয়ে শুরু করব যেগুলো আপনি IDE ব্যবহার করে কোটলিনে রূপান্তর করবেন। তারপর আমরা রূপান্তরিত কোডটি দেখব এবং দেখব কিভাবে আমরা এটিকে আরও বাগ্মী করে উন্নত করতে পারি এবং সাধারণ সমস্যাগুলি এড়াতে পারি।
তুমি কি শিখবে
তুমি জাভাকে কোটলিনে রূপান্তর করতে শিখবে। এর মাধ্যমে তুমি নিম্নলিখিত কোটলিন ভাষার বৈশিষ্ট্য এবং ধারণাগুলি শিখবে:
- বাতিলযোগ্যতা পরিচালনা করা
- সিঙ্গেলটন বাস্তবায়ন করা হচ্ছে
- ডেটা ক্লাস
- স্ট্রিং পরিচালনা করা
- এলভিস অপারেটর
- ধ্বংস করা
- বৈশিষ্ট্য এবং ব্যাকিং বৈশিষ্ট্য
- ডিফল্ট আর্গুমেন্ট এবং নামযুক্ত প্যারামিটার
- সংগ্রহের সাথে কাজ করা
- এক্সটেনশন ফাংশন
- শীর্ষ-স্তরের ফাংশন এবং পরামিতি
- কীওয়ার্ড
let,apply, ব্যবহার করাwithএবংrun
অনুমান
তোমার জাভার সাথে ইতিমধ্যেই পরিচিত হওয়া উচিত।
তোমার যা লাগবে
2. সেট আপ করা
একটি নতুন প্রকল্প তৈরি করুন
যদি আপনি IntelliJ IDEA ব্যবহার করেন, তাহলে Kotlin/JVM দিয়ে একটি নতুন জাভা প্রকল্প তৈরি করুন।
যদি আপনি অ্যান্ড্রয়েড স্টুডিও ব্যবহার করেন, তাহলে নো অ্যাক্টিভিটি টেমপ্লেট ব্যবহার করে একটি নতুন প্রকল্প তৈরি করুন। প্রকল্পের ভাষা হিসেবে কোটলিন বেছে নিন। ন্যূনতম SDK যেকোনো মূল্যের হতে পারে, এটি ফলাফলকে প্রভাবিত করবে না।
কোডটি
আমরা একটি User মডেল অবজেক্ট এবং একটি Repository singleton ক্লাস তৈরি করব যা User অবজেক্টের সাথে কাজ করে এবং ব্যবহারকারীদের তালিকা এবং ফর্ম্যাট করা ব্যবহারকারীর নাম প্রকাশ করে।
app/java/< yourpackagename > এর অধীনে User.java নামে একটি নতুন ফাইল তৈরি করুন এবং নিম্নলিখিত কোডটি পেস্ট করুন:
public class User {
@Nullable
private String firstName;
@Nullable
private String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
তুমি লক্ষ্য করবে যে তোমার IDE বলছে @Nullable সংজ্ঞায়িত নয়। তাই যদি তুমি Android Studio ব্যবহার করো তাহলে androidx.annotation.Nullable আমদানি করো, অথবা যদি তুমি IntelliJ ব্যবহার করো তাহলে org.jetbrains.annotations.Nullable আমদানি করো।
Repository.java নামে একটি নতুন ফাইল তৈরি করুন এবং নিম্নলিখিত কোডটি পেস্ট করুন:
import java.util.ArrayList;
import java.util.List;
public class Repository {
private static Repository INSTANCE = null;
private List<User> users = null;
public static Repository getInstance() {
if (INSTANCE == null) {
synchronized (Repository.class) {
if (INSTANCE == null) {
INSTANCE = new Repository();
}
}
}
return INSTANCE;
}
// keeping the constructor private to enforce the usage of getInstance
private Repository() {
User user1 = new User("Jane", "");
User user2 = new User("John", null);
User user3 = new User("Anne", "Doe");
users = new ArrayList();
users.add(user1);
users.add(user2);
users.add(user3);
}
public List<User> getUsers() {
return users;
}
public List<String> getFormattedUserNames() {
List<String> userNames = new ArrayList<>(users.size());
for (User user : users) {
String name;
if (user.getLastName() != null) {
if (user.getFirstName() != null) {
name = user.getFirstName() + " " + user.getLastName();
} else {
name = user.getLastName();
}
} else if (user.getFirstName() != null) {
name = user.getFirstName();
} else {
name = "Unknown";
}
userNames.add(name);
}
return userNames;
}
}
৩. বাতিলযোগ্যতা, ভ্যাল, ভার এবং ডেটা ক্লাস ঘোষণা করা
আমাদের IDE জাভা কোডকে স্বয়ংক্রিয়ভাবে কোটলিন কোডে রূপান্তর করার ক্ষেত্রে বেশ ভালো কাজ করতে পারে, কিন্তু কখনও কখনও এর জন্য একটু সাহায্যের প্রয়োজন হয়। আসুন আমাদের IDE কে রূপান্তরের প্রাথমিক পাস করতে দেই। তারপর আমরা ফলাফল কোডটি পরীক্ষা করে দেখব কিভাবে এবং কেন এটি এভাবে রূপান্তরিত হয়েছে তা বুঝতে।
User.java ফাইলে যান এবং এটিকে Kotlin এ রূপান্তর করুন: মেনু বার -> কোড -> জাভা ফাইলকে Kotlin ফাইলে রূপান্তর করুন ।
রূপান্তরের পরে যদি আপনার IDE সংশোধনের জন্য অনুরোধ করে, তাহলে Yes টিপুন।

আপনার নিম্নলিখিত কোটলিন কোডটি দেখা উচিত:
class User(var firstName: String?, var lastName: String?)
মনে রাখবেন যে User.java নাম পরিবর্তন করে User.kt রাখা হয়েছে। Kotlin ফাইলগুলির এক্সটেনশন .kt।
আমাদের জাভা User ক্লাসে আমাদের দুটি বৈশিষ্ট্য ছিল: firstName এবং lastName । প্রতিটির একটি গেটার এবং সেটার পদ্ধতি ছিল, যার ফলে এর মান পরিবর্তনযোগ্য ছিল। কোটলিনের পরিবর্তনযোগ্য ভেরিয়েবলের জন্য কীওয়ার্ড হল var , তাই কনভার্টার এই প্রতিটি বৈশিষ্ট্যের জন্য var ব্যবহার করে। যদি আমাদের জাভা বৈশিষ্ট্যগুলিতে কেবল গেটার থাকত, তবে সেগুলি কেবল পঠনযোগ্য হত এবং val ভেরিয়েবল হিসাবে ঘোষণা করা হত। val জাভাতে final কীওয়ার্ডের অনুরূপ।
কোটলিন এবং জাভার মধ্যে একটি গুরুত্বপূর্ণ পার্থক্য হল যে কোটলিন স্পষ্টভাবে নির্দিষ্ট করে যে কোনও ভেরিয়েবল একটি নাল মান গ্রহণ করতে পারে কিনা। এটি টাইপ ডিক্লেয়ারেশনে ? যোগ করে এটি করে।
যেহেতু আমরা firstName এবং lastName nullable হিসেবে চিহ্নিত করেছি, তাই অটো-কনভার্টারটি String? এর সাহায্যে প্রোপার্টিগুলিকে nullable হিসেবে স্বয়ংক্রিয়ভাবে চিহ্নিত করেছে। যদি আপনি আপনার জাভা সদস্যদের non-null হিসেবে টীকা করেন ( org.jetbrains.annotations.NotNull অথবা androidx.annotation.NonNull ব্যবহার করে), তাহলে কনভার্টার এটি সনাক্ত করবে এবং Kotlin-এও ক্ষেত্রগুলিকে non-null করে দেবে।
মৌলিক রূপান্তর ইতিমধ্যেই সম্পন্ন হয়েছে। কিন্তু আমরা এটিকে আরও বাগ্মীভাবে লিখতে পারি। দেখা যাক কিভাবে।
ডেটা ক্লাস
আমাদের User ক্লাসে শুধুমাত্র ডেটা থাকে। Kotlin-এ এই ভূমিকা সহ ক্লাসগুলির জন্য একটি কীওয়ার্ড রয়েছে: data । এই ক্লাসটিকে data ক্লাস হিসাবে চিহ্নিত করে, কম্পাইলার স্বয়ংক্রিয়ভাবে আমাদের জন্য গেটার এবং সেটার তৈরি করবে। এটি equals() , hashCode() , এবং toString() ফাংশনগুলিও অর্জন করবে।
আমাদের User ক্লাসে data কীওয়ার্ড যোগ করা যাক:
data class User(var firstName: String?, var lastName: String?)
জাভার মতো কোটলিনেও একটি প্রাইমারি কনস্ট্রাক্টর এবং এক বা একাধিক সেকেন্ডারি কনস্ট্রাক্টর থাকতে পারে। উপরের উদাহরণে দেখানো User ক্লাসের প্রাইমারি কনস্ট্রাক্টর। যদি আপনি এমন একটি জাভা ক্লাস কনভার্ট করেন যার একাধিক কনস্ট্রাক্টর আছে, তাহলে কনভার্টারটি স্বয়ংক্রিয়ভাবে কোটলিনেও একাধিক কনস্ট্রাক্টর তৈরি করবে। constructor কীওয়ার্ড ব্যবহার করে এগুলি সংজ্ঞায়িত করা হয়।
যদি আমরা এই ক্লাসের একটি উদাহরণ তৈরি করতে চাই, তাহলে আমরা এটি এভাবে করতে পারি:
val user1 = User("Jane", "Doe")
সমতা
কোটলিনে দুই ধরণের সমতা রয়েছে:
- স্ট্রাকচারাল ইকুয়ালিটি
==অপারেটর ব্যবহার করে এবং দুটি ইনস্ট্যান্স সমান কিনা তা নির্ধারণ করতেequals()কল করে। - রেফারেন্সিয়াল ইকুয়ালিটি
===অপারেটর ব্যবহার করে এবং দুটি রেফারেন্স একই বস্তুর দিকে নির্দেশ করে কিনা তা পরীক্ষা করে।
ডেটা ক্লাসের প্রাথমিক কনস্ট্রাক্টরে সংজ্ঞায়িত বৈশিষ্ট্যগুলি কাঠামোগত সমতা পরীক্ষা করার জন্য ব্যবহার করা হবে।
val user1 = User("Jane", "Doe")
val user2 = User("Jane", "Doe")
val structurallyEqual = user1 == user2 // true
val referentiallyEqual = user1 === user2 // false
৪. ডিফল্ট আর্গুমেন্ট, নামযুক্ত আর্গুমেন্ট
কোটলিনে, আমরা ফাংশন কলে আর্গুমেন্টগুলিতে ডিফল্ট মান নির্ধারণ করতে পারি। আর্গুমেন্ট বাদ দিলে ডিফল্ট মান ব্যবহার করা হয়। কোটলিনে, কনস্ট্রাক্টরগুলিও ফাংশন, তাই আমরা lastName এর ডিফল্ট মান null তা নির্দিষ্ট করতে ডিফল্ট আর্গুমেন্ট ব্যবহার করতে পারি। এটি করার জন্য, আমরা কেবল lastName কে null বরাদ্দ করব।
data class User(var firstName: String?, var lastName: String? = null)
// usage
val jane = User("Jane") // same as User("Jane", null)
val joe = User("Joe", "Doe")
যখন আপনার ফাংশনগুলি কল করা হয় তখন Kotlin আপনাকে আপনার আর্গুমেন্টগুলি লেবেল করার অনুমতি দেয়:
val john = User(firstName = "John", lastName = "Doe")
ভিন্ন ব্যবহারের ক্ষেত্রে, ধরা যাক যে firstName এর ডিফল্ট মান null আছে এবং lastName নেই। এই ক্ষেত্রে, যেহেতু ডিফল্ট প্যারামিটারটি কোনও ডিফল্ট মান ছাড়াই একটি প্যারামিটারের আগে থাকবে, তাই আপনাকে named আর্গুমেন্ট সহ ফাংশনটি কল করতে হবে:
data class User(var firstName: String? = null, var lastName: String?)
// usage
val jane = User(lastName = "Doe") // same as User(null, "Doe")
val john = User("John", "Doe")
কোটলিন কোডে ডিফল্ট মান একটি গুরুত্বপূর্ণ এবং প্রায়শই ব্যবহৃত ধারণা। আমাদের কোডল্যাবে আমরা সর্বদা একটি User অবজেক্ট ঘোষণায় প্রথম এবং শেষ নাম নির্দিষ্ট করতে চাই, তাই আমাদের ডিফল্ট মানের প্রয়োজন নেই।
৫. অবজেক্ট ইনিশিয়ালাইজেশন, কম্প্যানিয়ন অবজেক্ট এবং সিঙ্গেলটন
কোডল্যাব চালিয়ে যাওয়ার আগে, নিশ্চিত করুন যে আপনার User ক্লাসটি একটি data ক্লাস। এখন, Repository ক্লাসটিকে কোটলিনে রূপান্তর করা যাক। স্বয়ংক্রিয় রূপান্তর ফলাফলটি এইরকম দেখাবে:
import java.util.*
class Repository private constructor() {
private var users: MutableList<User?>? = null
fun getUsers(): List<User?>? {
return users
}
val formattedUserNames: List<String?>
get() {
val userNames: MutableList<String?> =
ArrayList(users!!.size)
for (user in users) {
var name: String
name = if (user!!.lastName != null) {
if (user!!.firstName != null) {
user!!.firstName + " " + user!!.lastName
} else {
user!!.lastName
}
} else if (user!!.firstName != null) {
user!!.firstName
} else {
"Unknown"
}
userNames.add(name)
}
return userNames
}
companion object {
private var INSTANCE: Repository? = null
val instance: Repository?
get() {
if (INSTANCE == null) {
synchronized(Repository::class.java) {
if (INSTANCE == null) {
INSTANCE =
Repository()
}
}
}
return INSTANCE
}
}
// keeping the constructor private to enforce the usage of getInstance
init {
val user1 = User("Jane", "")
val user2 = User("John", null)
val user3 = User("Anne", "Doe")
users = ArrayList<Any?>()
users.add(user1)
users.add(user2)
users.add(user3)
}
}
চলুন দেখি স্বয়ংক্রিয় রূপান্তরকারী কী করেছে:
-
usersতালিকা বাতিলযোগ্য কারণ ঘোষণার সময় অবজেক্টটি ইনস্ট্যান্টিয়েট করা হয়নি। - কোটলিনে
getUsers()এর মতো ফাংশনগুলিfunmodifier দিয়ে ঘোষণা করা হয়। -
getFormattedUserNames()পদ্ধতিটি এখনformattedUserNamesনামে একটি বৈশিষ্ট্য। - ব্যবহারকারীদের তালিকার পুনরাবৃত্তি (যা প্রাথমিকভাবে
getFormattedUserNames() এর অংশ ছিল) জাভা সিনট্যাক্সের চেয়ে আলাদা। -
staticফিল্ড এখন একটিcompanion objectব্লকের অংশ। - একটি
initব্লক যোগ করা হয়েছে
আরও এগিয়ে যাওয়ার আগে, কোডটি একটু পরিষ্কার করা যাক। আমরা যদি কনস্ট্রাক্টরটি দেখি, আমরা লক্ষ্য করি যে কনভার্টারটি আমাদের users একটি পরিবর্তনযোগ্য তালিকা তৈরি করেছে যাতে nullable বস্তু রয়েছে। যদিও তালিকাটি আসলে null হতে পারে, ধরা যাক এটি null ব্যবহারকারীদের ধরে রাখতে পারে না। তাহলে আসুন নিম্নলিখিতগুলি করি:
-
usersটাইপ ঘোষণার মধ্যে থাকা?User?শব্দটি সরিয়ে ফেলুন। -
getUsers()রিটার্ন টাইপের জন্য User?এUser?মুছে ফেলুন যাতে এটিList<User>?রিটার্ন করে।
ইনিট ব্লক
কোটলিনে, প্রাইমারি কনস্ট্রাক্টরে কোনও কোড থাকতে পারে না, তাই ইনিশিয়ালাইজেশন কোড init ব্লকে স্থাপন করা হয়। কার্যকারিতা একই।
class Repository private constructor() {
...
init {
val user1 = User("Jane", "")
val user2 = User("John", null)
val user3 = User("Anne", "Doe")
users = ArrayList<Any?>()
users.add(user1)
users.add(user2)
users.add(user3)
}
}
init কোডের বেশিরভাগ অংশই প্রোপার্টি ইনিশিয়ালাইজিং পরিচালনা করে। প্রোপার্টির ঘোষণার ক্ষেত্রেও এটি করা যেতে পারে। উদাহরণস্বরূপ, আমাদের Repository ক্লাসের কোটলিন সংস্করণে, আমরা দেখতে পাই যে ব্যবহারকারীদের প্রোপার্টি ঘোষণায় ইনিশিয়ালাইজ করা হয়েছিল।
private var users: MutableList<User>? = null
কোটলিনের static বৈশিষ্ট্য এবং পদ্ধতি
জাভাতে, আমরা ফিল্ড বা ফাংশনের জন্য static কীওয়ার্ড ব্যবহার করি যাতে বোঝা যায় যে তারা একটি ক্লাসের অন্তর্গত, কিন্তু ক্লাসের কোনও ইনস্ট্যান্সের সাথে সম্পর্কিত নয়। এই কারণেই আমরা আমাদের Repository ক্লাসে INSTANCE স্ট্যাটিক ফিল্ড তৈরি করেছি। এর জন্য Kotlin সমতুল্য হল companion object block। এখানে আপনি static fields এবং static functionsও ঘোষণা করবেন। কনভার্টার companion object block তৈরি করেছে এবং INSTANCE ফিল্ডটি এখানে স্থানান্তর করেছে।
সিঙ্গেলটন পরিচালনা করা
যেহেতু আমাদের Repository ক্লাসের শুধুমাত্র একটি ইনস্ট্যান্সের প্রয়োজন, আমরা জাভাতে সিঙ্গেলটন প্যাটার্ন ব্যবহার করেছি। কোটলিনের সাহায্যে, আপনি class কীওয়ার্ডটি object দিয়ে প্রতিস্থাপন করে কম্পাইলার স্তরে এই প্যাটার্নটি প্রয়োগ করতে পারেন।
প্রাইভেট কনস্ট্রাক্টরটি সরিয়ে ফেলুন এবং ক্লাসের সংজ্ঞাটি object Repository দিয়ে প্রতিস্থাপন করুন। companion অবজেক্টটিও সরিয়ে ফেলুন।
object Repository {
private var users: MutableList<User>? = null
fun getUsers(): List<User>? {
return users
}
val formattedUserNames: List<String>
get() {
val userNames: MutableList<String> =
ArrayList(users!!.size)
for (user in users) {
var name: String
name = if (user!!.lastName != null) {
if (user!!.firstName != null) {
user!!.firstName + " " + user!!.lastName
} else {
user!!.lastName
}
} else if (user!!.firstName != null) {
user!!.firstName
} else {
"Unknown"
}
userNames.add(name)
}
return userNames
}
// keeping the constructor private to enforce the usage of getInstance
init {
val user1 = User("Jane", "")
val user2 = User("John", null)
val user3 = User("Anne", "Doe")
users = ArrayList<Any?>()
users.add(user1)
users.add(user2)
users.add(user3)
}
}
object ক্লাস ব্যবহার করার সময়, আমরা কেবল অবজেক্টে সরাসরি ফাংশন এবং প্রোপার্টি কল করি, যেমন:
val formattedUserNames = Repository.formattedUserNames
মনে রাখবেন যে যদি কোনও প্রপার্টিতে ভিজিবিলিটি মডিফায়ার না থাকে, তাহলে এটি ডিফল্টরূপে পাবলিক থাকে, যেমনটি Repository অবজেক্টের formattedUserNames প্রপার্টির ক্ষেত্রে হয়।
৬. শূন্যতা পরিচালনা
Repository ক্লাসকে Kotlin-এ রূপান্তর করার সময়, স্বয়ংক্রিয় রূপান্তরকারী ব্যবহারকারীদের তালিকাকে বাতিলযোগ্য করে তোলে, কারণ এটি ঘোষণা করার সময় এটি কোনও অবজেক্টে ইনিশিয়ালাইজ করা হয়নি। ফলস্বরূপ, users অবজেক্টের সমস্ত ব্যবহারের জন্য, not-null assertion অপারেটর !! ব্যবহার করতে হবে। (আপনি রূপান্তরিত কোড জুড়ে users!! এবং user!! দেখতে পাবেন।) !! অপারেটর যেকোনো ভেরিয়েবলকে একটি নন-null টাইপে রূপান্তর করে, যাতে আপনি এতে বৈশিষ্ট্য অ্যাক্সেস করতে পারেন বা ফাংশন কল করতে পারেন। তবে, যদি ভেরিয়েবলের মান প্রকৃতপক্ষে null হয় তবে একটি ব্যতিক্রম থ্রো করা হবে। !! ব্যবহার করে, আপনি রানটাইমে ব্যতিক্রম থ্রো হওয়ার ঝুঁকি নিচ্ছেন।
পরিবর্তে, এই পদ্ধতিগুলির মধ্যে একটি ব্যবহার করে nullability পরিচালনা করতে পছন্দ করুন:
- একটি নাল চেক করা হচ্ছে (
if (users != null) {...}) - এলভিস অপারেটর ব্যবহার করে
?:(পরবর্তীতে কোডল্যাবে আলোচনা করা হয়েছে) - কিছু কোটলিন স্ট্যান্ডার্ড ফাংশন ব্যবহার করা (পরবর্তীতে কোডল্যাবে আলোচনা করা হবে)
আমাদের ক্ষেত্রে, আমরা জানি যে ব্যবহারকারীদের তালিকা বাতিল করার প্রয়োজন নেই, কারণ এটি অবজেক্ট তৈরির ঠিক পরেই ( init ব্লকে) শুরু হয়। সুতরাং আমরা যখন users অবজেক্ট ঘোষণা করি তখন আমরা সরাসরি তাৎক্ষণিকভাবে তাৎক্ষণিকভাবে প্রকাশ করতে পারি।
সংগ্রহের ধরণের ইনস্ট্যান্স তৈরি করার সময়, কোটলিন আপনার কোডকে আরও পঠনযোগ্য এবং নমনীয় করে তুলতে বেশ কয়েকটি সহায়ক ফাংশন সরবরাহ করে। এখানে আমরা users জন্য একটি MutableList ব্যবহার করছি:
private var users: MutableList<User>? = null
সহজ করার জন্য, আমরা mutableListOf() ফাংশন ব্যবহার করতে পারি এবং list element type প্রদান করতে পারি। mutableListOf<User>() একটি খালি তালিকা তৈরি করে যা User অবজেক্ট ধারণ করতে পারে। যেহেতু ভেরিয়েবলের ডেটা টাইপ এখন কম্পাইলার দ্বারা অনুমান করা যেতে পারে, তাই users প্রোপার্টির explicit type declaration সরিয়ে ফেলুন।
private val users = mutableListOf<User>()
আমরা var কে val তেও পরিবর্তন করেছি কারণ ব্যবহারকারীদের তালিকার জন্য একটি পঠনযোগ্য রেফারেন্স থাকবে। মনে রাখবেন যে রেফারেন্সটি কেবল পঠনযোগ্য, তাই এটি কখনই একটি নতুন তালিকার দিকে নির্দেশ করতে পারে না, তবে তালিকাটি নিজেই এখনও পরিবর্তনযোগ্য (আপনি উপাদান যোগ করতে বা অপসারণ করতে পারেন)।
যেহেতু users ভেরিয়েবলটি ইতিমধ্যেই ইনিশিয়ালাইজ করা হয়েছে, তাই init ব্লক থেকে এই ইনিশিয়ালাইজেশনটি সরিয়ে ফেলুন:
users = ArrayList<Any?>()
তাহলে init ব্লকটি দেখতে এরকম হওয়া উচিত:
init {
val user1 = User("Jane", "")
val user2 = User("John", null)
val user3 = User("Anne", "Doe")
users.add(user1)
users.add(user2)
users.add(user3)
}
এই পরিবর্তনগুলির মাধ্যমে, আমাদের users সম্পত্তি এখন অ-নাল, এবং আমরা সমস্ত অপ্রয়োজনীয় !! অপারেটর ঘটনাগুলি মুছে ফেলতে পারি। মনে রাখবেন যে আপনি এখনও অ্যান্ড্রয়েড স্টুডিওতে কম্পাইল ত্রুটি দেখতে পাবেন, তবে সেগুলি সমাধান করার জন্য কোডল্যাবের পরবর্তী কয়েকটি ধাপ অনুসরণ করুন।
val userNames: MutableList<String?> = ArrayList(users.size)
for (user in users) {
var name: String
name = if (user.lastName != null) {
if (user.firstName != null) {
user.firstName + " " + user.lastName
} else {
user.lastName
}
} else if (user.firstName != null) {
user.firstName
} else {
"Unknown"
}
userNames.add(name)
}
এছাড়াও, userNames মানের জন্য, যদি আপনি ArrayList এর ধরণটি Strings ধারণকারী হিসাবে নির্দিষ্ট করেন, তাহলে আপনি ঘোষণায় স্পষ্ট প্রকারটি সরাতে পারেন কারণ এটি অনুমান করা হবে।
val userNames = ArrayList<String>(users.size)
ধ্বংস করা
কোটলিন একটি বস্তুকে বিভিন্ন ভেরিয়েবলে রূপান্তরিত করার অনুমতি দেয়, যাকে বলা হয় destructuring declaration । আমরা একাধিক ভেরিয়েবল তৈরি করি এবং সেগুলি স্বাধীনভাবে ব্যবহার করতে পারি।
উদাহরণস্বরূপ, data ক্লাসগুলি ডিস্ট্রাক্টরিং সমর্থন করে যাতে আমরা for লুপের User অবজেক্টটিকে (firstName, lastName) এ ডিস্ট্রাক্ট করতে পারি। এটি আমাদের firstName এবং lastName মানগুলির সাথে সরাসরি কাজ করতে দেয়। নীচে দেখানো হিসাবে for লুপটি আপডেট করুন। user.firstName এর সমস্ত উদাহরণ firstName দিয়ে প্রতিস্থাপন করুন এবং user.lastName lastName দিয়ে প্রতিস্থাপন করুন।
for ((firstName, lastName) in users) {
var name: String
name = if (lastName != null) {
if (firstName != null) {
firstName + " " + lastName
} else {
lastName
}
} else if (firstName != null) {
firstName
} else {
"Unknown"
}
userNames.add(name)
}
যদি অভিব্যক্তি
userNames তালিকার নামগুলি এখনও আমাদের পছন্দের ফর্ম্যাটে নেই। যেহেতু lastName এবং firstName উভয়ই null হতে পারে, তাই ফর্ম্যাট করা ব্যবহারকারীর নামের তালিকা তৈরি করার সময় আমাদের nullability পরিচালনা করতে হবে। যদি কোনও নাম অনুপস্থিত থাকে তবে আমরা "Unknown" প্রদর্শন করতে চাই। যেহেতু name ভেরিয়েবলটি একবার সেট করার পরে পরিবর্তন করা হবে না, তাই আমরা var এর পরিবর্তে val ব্যবহার করতে পারি। প্রথমে এই পরিবর্তনটি করুন।
val name: String
name ভেরিয়েবল সেট করে এমন কোডটি একবার দেখে নিন। আপনার কাছে একটি ভেরিয়েবলকে if / else ব্লকের কোডের সমান সেট করা দেখতে নতুন মনে হতে পারে। এটি অনুমোদিত কারণ Kotlin-এ if এবং when এক্সপ্রেশনগুলি একটি মান প্রদান করে। if স্টেটমেন্টের শেষ লাইনটি name কে বরাদ্দ করা হবে। এই ব্লকের একমাত্র উদ্দেশ্য হল name মানটি শুরু করা।
মূলত, এখানে উপস্থাপিত যুক্তিটি হল যদি lastName null হয়, তাহলে name হয় firstName অথবা "Unknown" তে সেট করা হবে।
name = if (lastName != null) {
if (firstName != null) {
firstName + " " + lastName
} else {
lastName
}
} else if (firstName != null) {
firstName
} else {
"Unknown"
}
এলভিস অপারেটর
এই কোডটি elvis অপারেটর ?: ব্যবহার করে আরও বাকপটুভাবে লেখা যেতে পারে। elvis অপারেটর যদি null না হয় তবে তার বাম দিকের রাশিটি ফেরত দেবে, অথবা যদি বাম দিকের রাশিটি null হয় তবে তার ডান দিকের রাশিটি ফেরত দেবে।
তাহলে নিচের কোডে, firstName যদি null না হয় তাহলে রিটার্ন করা হবে। যদি firstName null হয়, তাহলে এক্সপ্রেশনটি ডানদিকের মান "Unknown" প্রদান করে:
name = if (lastName != null) {
...
} else {
firstName ?: "Unknown"
}
৭. স্ট্রিং টেমপ্লেট
Kotlin String টেমপ্লেট ব্যবহার করে String s এর সাথে কাজ করা সহজ করে তোলে। String টেমপ্লেট আপনাকে ভেরিয়েবলের আগে $ চিহ্ন ব্যবহার করে স্ট্রিং ডিক্লেয়ারেশনের ভিতরে ভেরিয়েবল রেফারেন্স করার সুযোগ দেয়। আপনি একটি স্ট্রিং ডিক্লেয়ারেশনের মধ্যে একটি এক্সপ্রেশনও রাখতে পারেন, { } এর মধ্যে এক্সপ্রেশনটি রেখে এবং তার আগে $ চিহ্ন ব্যবহার করে। উদাহরণ: ${user.firstName} ।
আপনার কোড বর্তমানে ব্যবহারকারীর নামের সাথে firstName এবং lastName একত্রিত করার জন্য স্ট্রিং কনক্যাটেনেশন ব্যবহার করে।
if (firstName != null) {
firstName + " " + lastName
}
পরিবর্তে, স্ট্রিং কনক্যাটেনেশনটি দিয়ে প্রতিস্থাপন করুন:
if (firstName != null) {
"$firstName $lastName"
}
স্ট্রিং টেমপ্লেট ব্যবহার করলে আপনার কোড সহজ হতে পারে।
যদি আপনার কোড লেখার জন্য আরও বাগ্মী উপায় থাকে, তাহলে আপনার IDE আপনাকে সতর্কীকরণ দেখাবে। আপনি কোডটিতে একটি তীক্ষ্ণ আন্ডারলাইন লক্ষ্য করবেন, এবং যখন আপনি এটির উপর কার্সার রাখবেন, তখন আপনি আপনার কোডটি কীভাবে রিফ্যাক্টর করবেন তার জন্য একটি পরামর্শ দেখতে পাবেন।
বর্তমানে, আপনি একটি সতর্কতা দেখতে পাবেন যে name ঘোষণাটি অ্যাসাইনমেন্টের সাথে যুক্ত করা যেতে পারে। আসুন এটি প্রয়োগ করি। যেহেতু name ভেরিয়েবলের ধরণটি অনুমান করা যেতে পারে, আমরা স্পষ্ট String টাইপ ঘোষণাটি সরিয়ে ফেলতে পারি। এখন আমাদের formattedUserNames দেখতে এরকম দেখাচ্ছে:
val formattedUserNames: List<String?>
get() {
val userNames = ArrayList<String>(users.size)
for ((firstName, lastName) in users) {
val name = if (lastName != null) {
if (firstName != null) {
"$firstName $lastName"
} else {
lastName
}
} else {
firstName ?: "Unknown"
}
userNames.add(name)
}
return userNames
}
আমরা আরও একটি পরিবর্তন করতে পারি। যদি প্রথম এবং শেষ নাম অনুপস্থিত থাকে তবে আমাদের UI লজিক "Unknown" প্রদর্শন করে, তাই আমরা null অবজেক্ট সমর্থন করছি না। সুতরাং, formattedUserNames এর ডেটা টাইপের জন্য List<String?> কে List<String> দিয়ে প্রতিস্থাপন করুন।
val formattedUserNames: List<String>
৮. সংগ্রহের উপর কার্যক্রম
আসুন formattedUserNames getter টি আরও ভালোভাবে দেখে নিই এবং দেখি কিভাবে আমরা এটিকে আরও বাগ্মী করে তুলতে পারি। এই মুহূর্তে কোডটি নিম্নলিখিত কাজ করে:
- স্ট্রিংগুলির একটি নতুন তালিকা তৈরি করে
- ব্যবহারকারীদের তালিকার মাধ্যমে পুনরাবৃত্তি করে
- ব্যবহারকারীর প্রথম এবং শেষ নামের উপর ভিত্তি করে প্রতিটি ব্যবহারকারীর জন্য ফর্ম্যাট করা নাম তৈরি করে।
- নতুন তৈরি তালিকাটি ফেরত পাঠায়
val formattedUserNames: List<String>
get() {
val userNames = ArrayList<String>(users.size)
for ((firstName, lastName) in users) {
val name = if (lastName != null) {
if (firstName != null) {
"$firstName $lastName"
} else {
lastName
}
} else {
firstName ?: "Unknown"
}
userNames.add(name)
}
return userNames
}
Kotlin সংগ্রহ রূপান্তরের একটি বিস্তৃত তালিকা প্রদান করে যা জাভা সংগ্রহ API এর ক্ষমতা প্রসারিত করে উন্নয়নকে দ্রুত এবং নিরাপদ করে। এর মধ্যে একটি হল map ফাংশন। এই ফাংশনটি মূল তালিকার প্রতিটি উপাদানে প্রদত্ত রূপান্তর ফাংশন প্রয়োগের ফলাফল ধারণ করে একটি নতুন তালিকা প্রদান করে। সুতরাং, একটি নতুন তালিকা তৈরি করে ব্যবহারকারীদের তালিকা ম্যানুয়ালি পুনরাবৃত্তি করার পরিবর্তে, আমরা map ফাংশনটি ব্যবহার করতে পারি এবং for লুপে আমাদের থাকা যুক্তিটি map বডির ভিতরে স্থানান্তর করতে পারি। ডিফল্টরূপে, map এ ব্যবহৃত বর্তমান তালিকা আইটেমের নাম হল it , তবে পঠনযোগ্যতার জন্য আপনি it আপনার নিজস্ব ভেরিয়েবলের নাম দিয়ে প্রতিস্থাপন করতে পারেন। আমাদের ক্ষেত্রে, আসুন এটির নাম user : রাখি।
val formattedUserNames: List<String>
get() {
return users.map { user ->
val name = if (user.lastName != null) {
if (user.firstName != null) {
"${user.firstName} ${user.lastName}"
} else {
user.lastName ?: "Unknown"
}
} else {
user.firstName ?: "Unknown"
}
name
}
}
লক্ষ্য করুন যে user.lastName null হলে "Unknown" রিটার্ন করার জন্য আমরা Elvis অপারেটর ব্যবহার করি, কারণ user.lastName String? ধরণের এবং name জন্য একটি String প্রয়োজন।
...
else {
user.lastName ?: "Unknown"
}
...
এটিকে আরও সহজ করার জন্য, আমরা name ভেরিয়েবলটি সম্পূর্ণরূপে মুছে ফেলতে পারি:
val formattedUserNames: List<String>
get() {
return users.map { user ->
if (user.lastName != null) {
if (user.firstName != null) {
"${user.firstName} ${user.lastName}"
} else {
user.lastName ?: "Unknown"
}
} else {
user.firstName ?: "Unknown"
}
}
}
৯. বৈশিষ্ট্য এবং ব্যাকিং বৈশিষ্ট্য
আমরা দেখেছি যে স্বয়ংক্রিয় রূপান্তরকারীটি getFormattedUserNames() ফাংশনটিকে formattedUserNames নামক একটি বৈশিষ্ট্য দিয়ে প্রতিস্থাপন করেছে যার একটি কাস্টম গেটার রয়েছে। হুডের নীচে, Kotlin এখনও একটি getFormattedUserNames() পদ্ধতি তৈরি করে যা একটি List ফেরত দেয়।
জাভাতে, আমরা গেটার এবং সেটার ফাংশনের মাধ্যমে আমাদের ক্লাসের বৈশিষ্ট্যগুলি প্রকাশ করব। কোটলিন আমাদেরকে একটি ক্লাসের বৈশিষ্ট্যগুলির মধ্যে আরও ভাল পার্থক্য করতে দেয়, যা ক্ষেত্র দিয়ে প্রকাশ করা হয় এবং কার্যকারিতা, যা একটি ক্লাস করতে পারে, ফাংশন দিয়ে প্রকাশ করা হয়। আমাদের ক্ষেত্রে, Repository ক্লাসটি খুবই সহজ এবং কোনও ক্রিয়া করে না তাই এতে কেবল ক্ষেত্র রয়েছে।
জাভা getFormattedUserNames() ফাংশনে যে লজিকটি ট্রিগার করা হয়েছিল তা এখন formattedUserNames Kotlin প্রোপার্টির গেটার কল করার সময় ট্রিগার করা হয়।
যদিও আমাদের কাছে formattedUserNames প্রপার্টির সাথে সম্পর্কিত কোনও ফিল্ড স্পষ্টভাবে নেই, Kotlin আমাদের field নামে একটি স্বয়ংক্রিয় ব্যাকিং ফিল্ড প্রদান করে যা আমরা প্রয়োজনে কাস্টম গেটার এবং সেটার থেকে অ্যাক্সেস করতে পারি।
তবে, কখনও কখনও আমরা কিছু অতিরিক্ত কার্যকারিতা চাই যা স্বয়ংক্রিয় ব্যাকিং ক্ষেত্র প্রদান করে না।
আসুন একটি উদাহরণ দিয়ে দেখা যাক।
আমাদের Repository ক্লাসের ভিতরে, আমাদের ব্যবহারকারীদের একটি পরিবর্তনযোগ্য তালিকা রয়েছে যা getUsers() ফাংশনে প্রকাশিত হচ্ছে যা আমাদের জাভা কোড থেকে তৈরি করা হয়েছে:
fun getUsers(): List<User>? {
return users
}
যেহেতু আমরা চাইনি যে Repository ক্লাসের কলাররা ব্যবহারকারীদের তালিকা পরিবর্তন করুক, তাই আমরা getUsers() ফাংশন তৈরি করেছি যা একটি পঠনযোগ্য List<User> প্রদান করে। Kotlin এর ক্ষেত্রে, আমরা এই ধরনের ক্ষেত্রে ফাংশনের পরিবর্তে বৈশিষ্ট্য ব্যবহার করতে পছন্দ করি। আরও স্পষ্টভাবে বলতে গেলে, আমরা একটি পঠনযোগ্য List<User> প্রকাশ করব যা একটি mutableListOf<User> দ্বারা সমর্থিত।
প্রথমে, users নাম পরিবর্তন করে _users রাখি। ভেরিয়েবলের নাম হাইলাইট করুন, Refactor > Rename এ ডান ক্লিক করুন। তারপর একটি public-read-only প্রোপার্টি যোগ করুন যা ব্যবহারকারীদের তালিকা প্রদান করে। আসুন একে users বলি:
private val _users = mutableListOf<User>()
val users: List<User>
get() = _users
এই মুহুর্তে, আপনি getUsers() পদ্ধতিটি মুছে ফেলতে পারেন।
উপরের পরিবর্তনের সাথে সাথে, private _users সম্পত্তিটি পাবলিক users সম্পত্তির ব্যাকিং সম্পত্তিতে পরিণত হয়। Repository ক্লাসের বাইরে, _users তালিকাটি পরিবর্তনযোগ্য নয়, কারণ ক্লাসের গ্রাহকরা শুধুমাত্র users এর মাধ্যমে তালিকাটি অ্যাক্সেস করতে পারবেন।
যখন কোটলিন কোড থেকে users কল করা হয়, তখন কোটলিন স্ট্যান্ডার্ড লাইব্রেরি থেকে List বাস্তবায়ন ব্যবহার করা হয়, যেখানে তালিকাটি পরিবর্তনযোগ্য নয়। যদি users জাভা থেকে ডাকা হয়, তাহলে java.util.List বাস্তবায়ন ব্যবহার করা হয়, যেখানে তালিকাটি পরিবর্তনযোগ্য এবং add() এবং remove() এর মতো ক্রিয়াকলাপ উপলব্ধ।
সম্পূর্ণ কোড:
object Repository {
private val _users = mutableListOf<User>()
val users: List<User>
get() = _users
val formattedUserNames: List<String>
get() {
return _users.map { user ->
if (user.lastName != null) {
if (user.firstName != null) {
"${user.firstName} ${user.lastName}"
} else {
user.lastName ?: "Unknown"
}
} else {
user.firstName ?: "Unknown"
}
}
}
init {
val user1 = User("Jane", "")
val user2 = User("John", null)
val user3 = User("Anne", "Doe")
_users.add(user1)
_users.add(user2)
_users.add(user3)
}
}
১০. শীর্ষ-স্তরের এবং এক্সটেনশন ফাংশন এবং বৈশিষ্ট্য
বর্তমানে Repository ক্লাস জানে কিভাবে একটি User অবজেক্টের জন্য ফরম্যাট করা ইউজার নেম গণনা করতে হয়। কিন্তু যদি আমরা একই ফর্ম্যাটিং লজিক অন্য ক্লাসে পুনরায় ব্যবহার করতে চাই, তাহলে আমাদের হয় এটি কপি করে পেস্ট করতে হবে অথবা User ক্লাসে স্থানান্তর করতে হবে।
কোটলিন যেকোনো ক্লাস, অবজেক্ট বা ইন্টারফেসের বাইরে ফাংশন এবং বৈশিষ্ট্য ঘোষণা করার ক্ষমতা প্রদান করে। উদাহরণস্বরূপ, একটি List একটি নতুন উদাহরণ তৈরি করতে আমরা যে mutableListOf() ফাংশনটি ব্যবহার করেছি তা ইতিমধ্যেই কোটলিন স্ট্যান্ডার্ড লাইব্রেরির Collections.kt এ সংজ্ঞায়িত করা হয়েছে।
জাভাতে, যখনই আপনার কোনও ইউটিলিটি কার্যকারিতার প্রয়োজন হয়, তখন আপনি সম্ভবত একটি Util ক্লাস তৈরি করবেন এবং সেই কার্যকারিতাটিকে একটি স্ট্যাটিক ফাংশন হিসাবে ঘোষণা করবেন। কোটলিনে আপনি ক্লাস ছাড়াই শীর্ষ-স্তরের ফাংশন ঘোষণা করতে পারেন। তবে, কোটলিন এক্সটেনশন ফাংশন তৈরি করার ক্ষমতাও প্রদান করে। এগুলি এমন ফাংশন যা একটি নির্দিষ্ট ধরণের প্রসারিত করে তবে ধরণের বাইরে ঘোষণা করা হয়।
এক্সটেনশন ফাংশন এবং বৈশিষ্ট্যের দৃশ্যমানতা দৃশ্যমানতা মডিফায়ার ব্যবহার করে সীমাবদ্ধ করা যেতে পারে। এগুলি শুধুমাত্র সেই ক্লাসগুলিতে ব্যবহার সীমাবদ্ধ করে যাদের এক্সটেনশনের প্রয়োজন হয় এবং নেমস্পেসকে দূষিত করে না।
User ক্লাসের জন্য, আমরা হয় একটি এক্সটেনশন ফাংশন যোগ করতে পারি যা ফর্ম্যাট করা নাম গণনা করে, অথবা আমরা ফর্ম্যাট করা নামটি একটি এক্সটেনশন প্রোপার্টিতে ধরে রাখতে পারি। এটি Repository ক্লাসের বাইরে একই ফাইলে যোগ করা যেতে পারে:
// extension function
fun User.getFormattedName(): String {
return if (lastName != null) {
if (firstName != null) {
"$firstName $lastName"
} else {
lastName ?: "Unknown"
}
} else {
firstName ?: "Unknown"
}
}
// extension property
val User.userFormattedName: String
get() {
return if (lastName != null) {
if (firstName != null) {
"$firstName $lastName"
} else {
lastName ?: "Unknown"
}
} else {
firstName ?: "Unknown"
}
}
// usage:
val user = User(...)
val name = user.getFormattedName()
val formattedName = user.userFormattedName
এরপর আমরা এক্সটেনশন ফাংশন এবং বৈশিষ্ট্যগুলি ব্যবহার করতে পারি যেন তারা User ক্লাসের অংশ।
যেহেতু ফরম্যাট করা নামটি User ক্লাসের একটি সম্পত্তি এবং Repository ক্লাসের কার্যকারিতা নয়, তাই আসুন extension প্রোপার্টি ব্যবহার করি। আমাদের Repository ফাইলটি এখন এরকম দেখাচ্ছে:
val User.formattedName: String
get() {
return if (lastName != null) {
if (firstName != null) {
"$firstName $lastName"
} else {
lastName ?: "Unknown"
}
} else {
firstName ?: "Unknown"
}
}
object Repository {
private val _users = mutableListOf<User>()
val users: List<User>
get() = _users
val formattedUserNames: List<String>
get() {
return _users.map { user -> user.formattedName }
}
init {
val user1 = User("Jane", "")
val user2 = User("John", null)
val user3 = User("Anne", "Doe")
_users.add(user1)
_users.add(user2)
_users.add(user3)
}
}
কোটলিন স্ট্যান্ডার্ড লাইব্রেরি বেশ কয়েকটি জাভা এপিআই-এর কার্যকারিতা প্রসারিত করার জন্য এক্সটেনশন ফাংশন ব্যবহার করে; Iterable এবং Collection এর অনেক কার্যকারিতা এক্সটেনশন ফাংশন হিসেবে প্রয়োগ করা হয়। উদাহরণস্বরূপ, পূর্ববর্তী ধাপে আমরা যে map ফাংশনটি ব্যবহার করেছি তা হল Iterable এর একটি এক্সটেনশন ফাংশন।
১১. স্কোপ ফাংশন: লেট, প্রয়োগ, উইথ, রান, ও
আমাদের Repository ক্লাস কোডে, আমরা _users তালিকায় বেশ কয়েকটি User অবজেক্ট যুক্ত করছি। Kotlin scope ফাংশনের সাহায্যে এই কলগুলিকে আরও সহজ করে তোলা যেতে পারে।
শুধুমাত্র একটি নির্দিষ্ট বস্তুর প্রসঙ্গে কোড কার্যকর করার জন্য, তার নামের উপর ভিত্তি করে বস্তুটি অ্যাক্সেস করার প্রয়োজন ছাড়াই, কোটলিন 5টি স্কোপ ফাংশন অফার করে: let , apply , with , run এবং also । এই ফাংশনগুলি আপনার কোডটি পড়া সহজ এবং আরও সংক্ষিপ্ত করে তোলে। সমস্ত স্কোপ ফাংশনের একটি রিসিভার ( this ) থাকে, একটি আর্গুমেন্ট ( it ) থাকতে পারে এবং একটি মান ফেরত দিতে পারে।
প্রতিটি ফাংশন কখন ব্যবহার করতে হবে তা মনে রাখতে সাহায্য করার জন্য এখানে একটি সহজ চিট শিট দেওয়া হল:

যেহেতু আমরা আমাদের Repository তে _users অবজেক্ট কনফিগার করছি, তাই আমরা apply ফাংশন ব্যবহার করে কোডটিকে আরও বাগ্মী করে তুলতে পারি:
init {
val user1 = User("Jane", "")
val user2 = User("John", null)
val user3 = User("Anne", "Doe")
_users.apply {
// this == _users
add(user1)
add(user2)
add(user3)
}
}
১২. শেষ করা
এই কোডল্যাবে, আমরা জাভা থেকে কোটলিনে কোড রূপান্তর শুরু করার জন্য আপনার প্রয়োজনীয় মৌলিক বিষয়গুলি কভার করেছি। এই রূপান্তরটি আপনার ডেভেলপমেন্ট প্ল্যাটফর্মের উপর নির্ভর করে না এবং আপনার লেখা কোডটি ইডিওম্যাটিক কোটলিন কিনা তা নিশ্চিত করতে সহায়তা করে।
ইডিওম্যাটিক কোটলিন লেখার কোডকে সংক্ষিপ্ত এবং মিষ্টি করে তোলে। কোটলিনের সমস্ত বৈশিষ্ট্যের সাহায্যে, আপনার কোডকে আরও নিরাপদ, আরও সংক্ষিপ্ত এবং আরও পঠনযোগ্য করে তোলার অনেক উপায় রয়েছে। উদাহরণস্বরূপ, আমরা ঘোষণায় সরাসরি ব্যবহারকারীদের সাথে _users তালিকাটি ইনস্ট্যান্টিয়েট করে, init ব্লকটি সরিয়ে আমাদের Repository ক্লাসটি অপ্টিমাইজ করতে পারি:
private val users = mutableListOf(User("Jane", ""), User("John", null), User("Anne", "Doe"))
আমরা বিভিন্ন ধরণের বিষয় নিয়ে আলোচনা করেছি, যেমন নালাবিলিটি, সিঙ্গেলটন, স্ট্রিং এবং কালেকশন পরিচালনা করা থেকে শুরু করে এক্সটেনশন ফাংশন, টপ-লেভেল ফাংশন, প্রোপার্টি এবং স্কোপ ফাংশনের মতো বিষয়। আমরা দুটি জাভা ক্লাস থেকে দুটি কোটলিন ক্লাসে গিয়েছিলাম যা এখন দেখতে এইরকম:
ব্যবহারকারী.কেটি
data class User(var firstName: String?, var lastName: String?)
রিপোজিটরি.কেটি
val User.formattedName: String
get() {
return if (lastName != null) {
if (firstName != null) {
"$firstName $lastName"
} else {
lastName ?: "Unknown"
}
} else {
firstName ?: "Unknown"
}
}
object Repository {
private val _users = mutableListOf(User("Jane", ""), User("John", null), User("Anne", "Doe"))
val users: List<User>
get() = _users
val formattedUserNames: List<String>
get() = _users.map { user -> user.formattedName }
}
এখানে জাভা কার্যকারিতা এবং কোটলিনে তাদের ম্যাপিংয়ের একটি TL;DR দেওয়া হল:
জাভা | কোটলিন |
| |
| |
| |
যে ক্লাসটি কেবল ডেটা ধারণ করে | |
কনস্ট্রাক্টরে ইনিশিয়ালাইজেশন | |
| একটি |
সিঙ্গেলটন ক্লাস | |
কোটলিন সম্পর্কে আরও জানতে এবং আপনার প্ল্যাটফর্মে এটি কীভাবে ব্যবহার করবেন, এই রিসোর্সগুলি দেখুন: