1. স্বাগতম!
এই কোডল্যাবে, আপনি কীভাবে আপনার কোড জাভা থেকে কোটলিনে রূপান্তর করবেন তা শিখবেন। আপনি কোটলিন ভাষার কনভেনশনগুলি কী এবং আপনি যে কোডটি লিখছেন তা সেগুলি অনুসরণ করে তা কীভাবে নিশ্চিত করবেন তাও শিখবেন৷
এই কোডল্যাবটি জাভা ব্যবহার করে এমন যেকোন ডেভেলপারের জন্য উপযুক্ত যারা তাদের প্রোজেক্ট কোটলিনে স্থানান্তরিত করার কথা ভাবছেন। আমরা কয়েকটি জাভা ক্লাস দিয়ে শুরু করব যা আপনি IDE ব্যবহার করে Kotlin-এ রূপান্তর করবেন। তারপরে আমরা রূপান্তরিত কোডটি একবার দেখব এবং দেখব কিভাবে আমরা এটিকে আরও বাহাদুরী করে উন্নত করতে পারি এবং সাধারণ সমস্যাগুলি এড়াতে পারি৷
আপনি কি শিখবেন
আপনি শিখবেন কিভাবে জাভাকে কোটলিনে রূপান্তর করতে হয়। এটি করার মাধ্যমে আপনি নিম্নলিখিত কোটলিন ভাষার বৈশিষ্ট্য এবং ধারণাগুলি শিখবেন:
- শূন্যতা হ্যান্ডলিং
- সিঙ্গেলটন বাস্তবায়ন করা
- ডেটা ক্লাস
- হ্যান্ডলিং স্ট্রিং
- এলভিস অপারেটর
- ধ্বংস করা
- বৈশিষ্ট্য এবং ব্যাকিং বৈশিষ্ট্য
- ডিফল্ট আর্গুমেন্ট এবং নাম পরামিতি
- সংগ্রহ নিয়ে কাজ করা
- এক্সটেনশন ফাংশন
- শীর্ষ-স্তরের ফাংশন এবং পরামিতি
-
let
,apply
,with
, এবং কীওয়ার্ডrun
অনুমান
আপনি ইতিমধ্যে জাভা সঙ্গে পরিচিত হওয়া উচিত.
আপনি কি প্রয়োজন হবে
2. সেট আপ করা হচ্ছে
একটি নতুন প্রকল্প তৈরি করুন
আপনি যদি IntelliJ IDEA ব্যবহার করেন, Kotlin/JVM এর সাথে একটি নতুন জাভা প্রকল্প তৈরি করুন।
আপনি যদি অ্যান্ড্রয়েড স্টুডিও ব্যবহার করে থাকেন, নো অ্যাক্টিভিটি টেমপ্লেট দিয়ে একটি নতুন প্রকল্প তৈরি করুন। প্রকল্প ভাষা হিসাবে Kotlin চয়ন করুন. ন্যূনতম SDK যে কোনও মূল্যের হতে পারে, এটি ফলাফলকে প্রভাবিত করবে না।
কোড
আমরা একটি User
মডেল অবজেক্ট এবং একটি Repository
সিঙ্গলটন ক্লাস তৈরি করব যা 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
সংজ্ঞায়িত করা হয়নি। সুতরাং আপনি যদি অ্যান্ড্রয়েড স্টুডিও ব্যবহার করেন তাহলে androidx.annotation.Nullable
, অথবা org.jetbrains.annotations.Nullable
যদি আপনি IntelliJ ব্যবহার করেন তাহলে আমদানি করুন।
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;
}
}
3. শূন্যতা, val, var এবং ডেটা ক্লাস ঘোষণা করা
আমাদের IDE স্বয়ংক্রিয়ভাবে জাভা কোডকে Kotlin কোডে রূপান্তর করার জন্য একটি সুন্দর কাজ করতে পারে তবে কখনও কখনও এটির জন্য একটু সাহায্যের প্রয়োজন হয়। আসুন আমাদের IDE-কে কনভার্সনে প্রাথমিক পাস করা যাক। তারপর কিভাবে এবং কেন এটি এইভাবে রূপান্তরিত হয়েছে তা বোঝার জন্য আমরা ফলাফল কোডের মধ্য দিয়ে যাব।
User.java
ফাইলে যান এবং এটিকে Kotlin এ রূপান্তর করুন: মেনু বার -> কোড -> Java ফাইলকে Kotlin ফাইলে রূপান্তর করুন ।
যদি আপনার IDE রূপান্তরের পরে সংশোধনের জন্য অনুরোধ করে, হ্যাঁ টিপুন।
আপনি নিম্নলিখিত Kotlin কোড দেখতে হবে:
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?
. আপনি যদি আপনার জাভা সদস্যদের নন-নাল হিসেবে ( org.jetbrains.annotations.NotNull
বা androidx.annotation.NonNull
ব্যবহার করে) টীকা দেন, তাহলে রূপান্তরকারী এটিকে চিনবে এবং ক্ষেত্রগুলিকে কোটলিনেও নন-নাল করে দেবে।
প্রাথমিক রূপান্তর ইতিমধ্যে সম্পন্ন হয়েছে. তবে আমরা এটি আরও বাজেভাবে লিখতে পারি। দেখা যাক কিভাবে।
ডেটা ক্লাস
আমাদের User
শ্রেণী শুধুমাত্র ডেটা ধারণ করে। কোটলিনের এই ভূমিকা সহ ক্লাসগুলির জন্য একটি কীওয়ার্ড রয়েছে: 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
4. ডিফল্ট আর্গুমেন্ট, নামযুক্ত আর্গুমেন্ট
কোটলিনে, আমরা ফাংশন কলে আর্গুমেন্টে ডিফল্ট মান নির্ধারণ করতে পারি। আর্গুমেন্ট বাদ দিলে ডিফল্ট মান ব্যবহার করা হয়। Kotlin-এ, কনস্ট্রাক্টরগুলিও ফাংশন, তাই আমরা নির্দিষ্ট করতে ডিফল্ট আর্গুমেন্ট ব্যবহার করতে পারি যে 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")
যখন আপনার ফাংশনগুলি কল করা হয় তখন কোটলিন আপনাকে আপনার আর্গুমেন্ট লেবেল করার অনুমতি দেয়:
val john = User(firstName = "John", lastName = "Doe")
একটি ভিন্ন ব্যবহারের ক্ষেত্রে, ধরা যাক যে firstName
এর ডিফল্ট মান হিসাবে null
আছে এবং lastName
নেই। এই ক্ষেত্রে, যেহেতু ডিফল্ট প্যারামিটারটি কোনও ডিফল্ট মান ছাড়াই একটি প্যারামিটারের আগে থাকবে, আপনাকে অবশ্যই নামযুক্ত আর্গুমেন্ট সহ ফাংশনটি কল করতে হবে:
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
অবজেক্ট ঘোষণায় প্রথম এবং শেষ নামটি নির্দিষ্ট করতে চাই, তাই আমাদের ডিফল্ট মানগুলির প্রয়োজন নেই।
5. অবজেক্ট ইনিশিয়ালাইজেশন, কম্প্যানিয়ন অবজেক্ট এবং সিঙ্গেলটন
কোডল্যাব চালিয়ে যাওয়ার আগে, নিশ্চিত করুন যে আপনার User
ক্লাস একটি data
ক্লাস। এখন, Repository
ক্লাসকে Kotlin-এ রূপান্তর করা যাক। স্বয়ংক্রিয় রূপান্তর ফলাফল এই মত হওয়া উচিত:
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()
fun
মডিফায়ার দিয়ে ঘোষণা করা হয় -
getFormattedUserNames()
পদ্ধতিটি এখনformattedUserNames
নামে একটি সম্পত্তি - ব্যবহারকারীদের তালিকার পুনরাবৃত্তি (যেটি প্রাথমিকভাবে
getFormattedUserNames(
) এর অংশ ছিল) জাভা-এর চেয়ে আলাদা সিনট্যাক্স রয়েছে -
static
ক্ষেত্রটি এখন একটিcompanion object
ব্লকের অংশ - একটি
init
ব্লক যোগ করা হয়েছে
আমরা আরও এগিয়ে যাওয়ার আগে, আসুন কোডটি কিছুটা পরিষ্কার করি। আমরা যদি কনস্ট্রাক্টরের দিকে তাকাই, আমরা লক্ষ্য করি যে কনভার্টারটি আমাদের users
একটি পরিবর্তনযোগ্য তালিকা তৈরি করেছে যা বাতিলযোগ্য বস্তু ধারণ করে। যদিও তালিকাটি প্রকৃতপক্ষে নাল হতে পারে, আসুন ধরে নেওয়া যাক এটি নাল ব্যবহারকারীদের ধরে রাখতে পারে না। তাহলে চলুন নিম্নলিখিতগুলি করি:
- সরান
?
User?
users
টাইপ ঘোষণা মধ্যে - সরান
?
User?
getUsers()
এর রিটার্ন টাইপের জন্য তাই এটি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
স্ট্যাটিক ফিল্ড তৈরি করেছি। এর জন্য কোটলিন সমতুল্য হল companion object
ব্লক। এখানে আপনি স্ট্যাটিক ক্ষেত্র এবং স্ট্যাটিক ফাংশন ঘোষণা করবেন। কনভার্টারটি কম্প্যানিয়ন অবজেক্ট ব্লক তৈরি করেছে এবং INSTANCE
ফিল্ডটি এখানে সরিয়ে দিয়েছে।
সিঙ্গেলটন হ্যান্ডলিং
যেহেতু আমাদের Repository
ক্লাসের শুধুমাত্র একটি উদাহরণ প্রয়োজন, আমরা জাভাতে সিঙ্গেলটন প্যাটার্ন ব্যবহার করেছি। Kotlin এর সাথে, আপনি কম্পাইলার লেভেলে class
কীওয়ার্ডটিকে object
সাথে প্রতিস্থাপন করে এই প্যাটার্নটি প্রয়োগ করতে পারেন।
প্রাইভেট কনস্ট্রাক্টর সরান এবং object Repository
দিয়ে শ্রেণী সংজ্ঞা প্রতিস্থাপন করুন। সঙ্গী বস্তুটিও সরান।
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
সম্পত্তির ক্ষেত্রে।
6. শূন্যতা হ্যান্ডলিং
Repository
ক্লাসকে কোটলিনে রূপান্তর করার সময়, স্বয়ংক্রিয় রূপান্তরকারী ব্যবহারকারীদের তালিকা বাতিলযোগ্য করে তোলে, কারণ এটি ঘোষণা করার সময় এটি একটি অবজেক্টে আরম্ভ করা হয়নি। ফলস্বরূপ, users
সমস্ত ব্যবহারের জন্য অবজেক্ট, নট-নাল অ্যাসারশন অপারেটর !!
ব্যবহার করা প্রয়োজন। (আপনি users!!
এবং user!!
রূপান্তরিত কোড জুড়ে।) the !!
অপারেটর যেকোনো ভেরিয়েবলকে নন-নাল টাইপে রূপান্তর করে, যাতে আপনি বৈশিষ্ট্যগুলি অ্যাক্সেস করতে পারেন বা এতে ফাংশন কল করতে পারেন। যাইহোক, একটি ব্যতিক্রম নিক্ষেপ করা হবে যদি পরিবর্তনশীল মান প্রকৃতপক্ষে শূন্য হয়। ব্যবহার করে !!
, আপনি রানটাইমে ব্যতিক্রমগুলি নিক্ষিপ্ত হওয়ার ঝুঁকি নিচ্ছেন৷
পরিবর্তে, এই পদ্ধতিগুলির মধ্যে একটি ব্যবহার করে অকার্যকরতা পরিচালনা করতে পছন্দ করুন:
- একটি নাল চেক করা হচ্ছে (
if (users != null) {...}
) - এলভিস অপারেটর ব্যবহার করে
?:
(পরে কোডল্যাবে আচ্ছাদিত) - কিছু কোটলিন স্ট্যান্ডার্ড ফাংশন ব্যবহার করে (পরে কোডল্যাবে কভার করা হয়েছে)
আমাদের ক্ষেত্রে, আমরা জানি যে ব্যবহারকারীদের তালিকাটি বাতিলযোগ্য হতে হবে না, যেহেতু এটি অবজেক্টটি তৈরি হওয়ার পরে ( init
ব্লকে) শুরু হয়। এইভাবে আমরা যখন এটি ঘোষণা করি তখন আমরা users
অবজেক্টকে সরাসরি তাত্ক্ষণিক করতে পারি।
সংগ্রহের প্রকারের দৃষ্টান্ত তৈরি করার সময়, কোটলিন আপনার কোডকে আরও পঠনযোগ্য এবং নমনীয় করতে বেশ কয়েকটি সহায়ক ফাংশন প্রদান করে। এখানে আমরা users
জন্য একটি MutableList
ব্যবহার করছি:
private var users: MutableList<User>? = null
সরলতার জন্য, আমরা mutableListOf()
ফাংশন ব্যবহার করতে পারি এবং তালিকা উপাদানের ধরন প্রদান করতে পারি। mutableListOf<User>()
একটি খালি তালিকা তৈরি করে যা User
বস্তুগুলিকে ধরে রাখতে পারে। যেহেতু ভেরিয়েবলের ডেটা টাইপ এখন কম্পাইলার দ্বারা অনুমান করা যেতে পারে, তাই users
সম্পত্তির স্পষ্ট টাইপ ঘোষণা মুছে ফেলুন।
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)
ধ্বংস করা
Kotlin destructuring declaration নামে একটি সিনট্যাক্স ব্যবহার করে একটি বস্তুকে অনেকগুলি ভেরিয়েবলে ধ্বংস করার অনুমতি দেয়। আমরা একাধিক ভেরিয়েবল তৈরি করি এবং সেগুলি স্বাধীনভাবে ব্যবহার করতে পারি।
উদাহরণস্বরূপ, data
ক্লাসগুলি ধ্বংসকে সমর্থন করে যাতে আমরা (firstName, lastName)
এর for
লুপে User
অবজেক্টটিকে ধ্বংস করতে পারি। এটি আমাদের 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)
}
যদি অভিব্যক্তি
ব্যবহারকারীর নামের তালিকার নামগুলি আমরা এখনও যে বিন্যাসে চাই তা পুরোপুরি নয়। যেহেতু lastName
এবং firstName
উভয়ই null
হতে পারে, তাই যখন আমরা বিন্যাসকৃত ব্যবহারকারীর নামের তালিকা তৈরি করি তখন আমাদের শূন্যতা পরিচালনা করতে হবে। যেকোনো একটি নাম অনুপস্থিত থাকলে আমরা "Unknown"
প্রদর্শন করতে চাই। যেহেতু name
ভেরিয়েবলটি একবার সেট করার পরে পরিবর্তন করা হবে না, তাই আমরা var
এর পরিবর্তে val
ব্যবহার করতে পারি। প্রথমে এই পরিবর্তন করুন।
val name: String
নাম পরিবর্তনশীল সেট করে এমন কোডটি দেখুন। এটি আপনার কাছে নতুন মনে হতে পারে যে একটি পরিবর্তনশীলকে কোডের if
/ else
ব্লকের সমান সেট করা হচ্ছে। এটি অনুমোদিত কারণ কোটলিনে if
এবং when
অভিব্যক্তি হয় - তারা একটি মান প্রদান করে। if
স্টেটমেন্টের শেষ লাইনটি name
সাথে বরাদ্দ করা হবে। এই ব্লকের একমাত্র উদ্দেশ্য হল name
মান শুরু করা।
মূলত, এখানে উপস্থাপিত এই যুক্তি হল যদি lastName
শূন্য হয়, name
হয় firstName
বা "Unknown"
-এ সেট করা হয়।
name = if (lastName != null) {
if (firstName != null) {
firstName + " " + lastName
} else {
lastName
}
} else if (firstName != null) {
firstName
} else {
"Unknown"
}
এলভিস অপারেটর
এলভিস অপারেটর ব্যবহার করে এই কোডটি আরও বাজেভাবে লেখা যেতে পারে ?:
। এলভিস অপারেটর তার বাম দিকের অভিব্যক্তিটি ফিরিয়ে দেবে যদি এটি নাল না হয়, বা তার ডান দিকের অভিব্যক্তিটি, যদি বাম দিকে শূন্য হয়।
তাই নিচের কোডে, firstName
রিটার্ন করা হয় যদি এটি নাল না হয়। যদি firstName
শূন্য হয়, অভিব্যক্তিটি ডানদিকের মান প্রদান করে, "Unknown"
:
name = if (lastName != null) {
...
} else {
firstName ?: "Unknown"
}
7. স্ট্রিং টেমপ্লেট
Kotlin স্ট্রিং টেমপ্লেটের সাথে String
এর সাথে কাজ করা সহজ করে তোলে। স্ট্রিং টেমপ্লেট আপনাকে ভেরিয়েবলের আগে $ চিহ্ন ব্যবহার করে স্ট্রিং ঘোষণার ভিতরে ভেরিয়েবল উল্লেখ করতে দেয়। আপনি একটি স্ট্রিং ঘোষণার মধ্যে একটি অভিব্যক্তি রাখতে পারেন, { } এর মধ্যে অভিব্যক্তি স্থাপন করে এবং এর আগে $ চিহ্ন ব্যবহার করে। উদাহরণ: ${user.firstName}
।
আপনার কোড বর্তমানে ব্যবহারকারীর নামের সাথে firstName
এবং lastName
একত্রিত করতে স্ট্রিং সংযোজন ব্যবহার করে।
if (firstName != null) {
firstName + " " + lastName
}
পরিবর্তে, এর সাথে স্ট্রিং সংযোগটি প্রতিস্থাপন করুন:
if (firstName != null) {
"$firstName $lastName"
}
স্ট্রিং টেমপ্লেট ব্যবহার করে আপনার কোড সহজ করতে পারে।
আপনার আইডিই আপনাকে সতর্কতা দেখাবে যদি আপনার কোড লেখার জন্য আরও বাজে উপায় থাকে। আপনি কোডে একটি স্কুইগ্লি আন্ডারলাইন লক্ষ্য করবেন এবং যখন আপনি এটির উপর কার্সার করবেন, আপনি কীভাবে আপনার কোড রিফ্যাক্টর করবেন তার জন্য একটি পরামর্শ দেখতে পাবেন।
বর্তমানে, আপনি একটি সতর্কতা দেখতে পাবেন যে 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"
প্রদর্শন করে, তাই আমরা শূন্য বস্তু সমর্থন করছি না। সুতরাং, formattedUserNames
ইউজারনেমের ডেটা টাইপের জন্য List<String?>
List<String>
দিয়ে প্রতিস্থাপন করুন।
val formattedUserNames: List<String>
8. সংগ্রহের উপর অপারেশন
চলুন 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
}
Kotlin সংগ্রহ রূপান্তরের একটি বিস্তৃত তালিকা প্রদান করে যা জাভা সংগ্রহ API-এর ক্ষমতা প্রসারিত করে উন্নয়নকে দ্রুত এবং নিরাপদ করে। তাদের মধ্যে একটি map
ফাংশন. এই ফাংশনটি মূল তালিকার প্রতিটি উপাদানে প্রদত্ত ট্রান্সফর্ম ফাংশন প্রয়োগের ফলাফল ধারণকারী একটি নতুন তালিকা প্রদান করে। সুতরাং, একটি নতুন তালিকা তৈরি করার পরিবর্তে এবং ব্যবহারকারীদের ম্যানুয়ালি তালিকার মাধ্যমে পুনরাবৃত্তি করার পরিবর্তে, আমরা map
ফাংশনটি ব্যবহার করতে পারি এবং map
বডির ভিতরে for
যে যুক্তিটি ছিল তা সরাতে পারি। ডিফল্টরূপে, 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
শূন্য হলে আমরা Elvis অপারেটর ব্যবহার করি "Unknown"
ফেরত দিতে, যেহেতু 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"
}
}
}
9. বৈশিষ্ট্য এবং ব্যাকিং বৈশিষ্ট্য
আমরা দেখেছি যে স্বয়ংক্রিয় রূপান্তরকারী getFormattedUserNames()
ফাংশনটিকে formattedUserNames
নামে একটি বৈশিষ্ট্য দিয়ে প্রতিস্থাপন করেছে যার একটি কাস্টম গেটার রয়েছে। হুডের অধীনে, Kotlin এখনও একটি getFormattedUserNames()
পদ্ধতি তৈরি করে যা একটি List
প্রদান করে।
জাভাতে, আমরা গেটার এবং সেটার ফাংশনের মাধ্যমে আমাদের ক্লাসের বৈশিষ্ট্যগুলি প্রকাশ করব। Kotlin আমাদের একটি ক্লাসের বৈশিষ্ট্যগুলির মধ্যে একটি ভাল পার্থক্য করার অনুমতি দেয়, ক্ষেত্রগুলির সাথে প্রকাশ করা হয়, এবং কার্যকারিতাগুলি, কর্ম যা একটি ক্লাস করতে পারে, ফাংশনগুলির সাথে প্রকাশ করা হয়। আমাদের ক্ষেত্রে, Repository
ক্লাসটি খুব সহজ এবং কোন কাজ করে না তাই এটির শুধুমাত্র ক্ষেত্র রয়েছে।
জাভা getFormattedUserNames()
ফাংশনে যে লজিকটি ট্রিগার করা হয়েছিল সেটি এখন formattedUserNames
কোটলিন প্রপার্টির গেটারকে কল করার সময় ট্রিগার করা হয়েছে।
যদিও আমাদের কাছে স্পষ্টভাবে formattedUserNames
সম্পত্তির সাথে সম্পর্কিত একটি ক্ষেত্র নেই, Kotlin আমাদের একটি স্বয়ংক্রিয় ব্যাকিং ক্ষেত্র নামক field
প্রদান করে যা আমরা কাস্টম গেটার এবং সেটারের থেকে প্রয়োজন হলে অ্যাক্সেস করতে পারি।
কখনও কখনও, যাইহোক, আমরা কিছু অতিরিক্ত কার্যকারিতা চাই যা স্বয়ংক্রিয় ব্যাকিং ক্ষেত্র প্রদান করে না।
এর একটি উদাহরণ মাধ্যমে যান.
আমাদের Repository
ক্লাসের ভিতরে, আমাদের কাছে ব্যবহারকারীদের একটি পরিবর্তনযোগ্য তালিকা রয়েছে যা getUsers()
ফাংশনে প্রকাশ করা হচ্ছে যা আমাদের জাভা কোড থেকে তৈরি হয়েছিল:
fun getUsers(): List<User>? {
return users
}
যেহেতু আমরা Repository
ক্লাসের কলাররা ব্যবহারকারীদের তালিকা পরিবর্তন করতে চাইনি, তাই আমরা getUsers()
ফাংশন তৈরি করেছি যা একটি পঠনযোগ্য List<User>
> প্রদান করে। কোটলিনের সাথে, আমরা এই জাতীয় ক্ষেত্রে ফাংশনের পরিবর্তে বৈশিষ্ট্যগুলি ব্যবহার করতে পছন্দ করি। আরও স্পষ্টভাবে, আমরা একটি শুধুমাত্র-পঠনযোগ্য List<User>
প্রকাশ করব যা একটি mutableListOf<User>
দ্বারা সমর্থিত।
প্রথমে users
নাম পরিবর্তন করে _users
করা যাক। ভেরিয়েবলের নাম হাইলাইট করুন, রিফ্যাক্টরে ডান ক্লিক করুন > ভেরিয়েবলের নাম পরিবর্তন করুন । তারপর একটি সর্বজনীন পঠনযোগ্য সম্পত্তি যোগ করুন যা ব্যবহারকারীদের একটি তালিকা প্রদান করে। আসুন এটিকে users
বলি:
private val _users = mutableListOf<User>()
val users: List<User>
get() = _users
এই মুহুর্তে, আপনি getUsers()
পদ্ধতিটি মুছে ফেলতে পারেন।
উপরের পরিবর্তনের সাথে, ব্যক্তিগত _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)
}
}
10. শীর্ষ-স্তরের এবং এক্সটেনশন ফাংশন এবং বৈশিষ্ট্য
এই মুহূর্তে Repository
ক্লাস জানে কিভাবে একটি User
অবজেক্টের জন্য ফরম্যাট করা ইউজার নেম গণনা করতে হয়। কিন্তু আমরা যদি অন্য ক্লাসে একই ফরম্যাটিং লজিক পুনঃব্যবহার করতে চাই, তাহলে আমাদের হয় কপি করে পেস্ট করতে হবে অথবা User
ক্লাসে সরাতে হবে।
Kotlin যে কোনো শ্রেণী, বস্তু, বা ইন্টারফেসের বাইরে ফাংশন এবং বৈশিষ্ট্য ঘোষণা করার ক্ষমতা প্রদান করে। উদাহরণস্বরূপ, একটি List
একটি নতুন উদাহরণ তৈরি করতে আমরা যে mutableListOf()
ফাংশনটি ব্যবহার করেছি তা ইতিমধ্যে Kotlin স্ট্যান্ডার্ড লাইব্রেরি থেকে 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
ক্লাসের কার্যকারিতা নয়, আসুন এক্সটেনশন সম্পত্তি ব্যবহার করি। আমাদের 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)
}
}
কোটলিন স্ট্যান্ডার্ড লাইব্রেরি বিভিন্ন জাভা API-এর কার্যকারিতা প্রসারিত করতে এক্সটেনশন ফাংশন ব্যবহার করে; Iterable
এবং Collection
অনেক কার্যকারিতা এক্সটেনশন ফাংশন হিসাবে প্রয়োগ করা হয়। উদাহরণস্বরূপ, পূর্ববর্তী ধাপে আমরা যে map
ফাংশনটি ব্যবহার করেছি তা হল Iterable
এ একটি এক্সটেনশন ফাংশন।
11. স্কোপ ফাংশন: let, apply, with, run, also
আমাদের Repository
ক্লাস কোডে, আমরা _users
তালিকায় বেশ কিছু User
অবজেক্ট যোগ করছি। কোটলিন স্কোপ ফাংশনগুলির সাহায্যে এই কলগুলিকে আরও বাজে করা যেতে পারে৷
শুধুমাত্র একটি নির্দিষ্ট অবজেক্টের প্রেক্ষাপটে কোড চালানোর জন্য, তার নামের উপর ভিত্তি করে অবজেক্ট অ্যাক্সেস করার প্রয়োজন ছাড়াই, Kotlin 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)
}
}
12. মোড়ানো
এই কোডল্যাবে, আমরা আপনার কোড জাভা থেকে কোটলিনে রূপান্তর করা শুরু করার জন্য প্রয়োজনীয় মৌলিক বিষয়গুলি কভার করেছি। এই রূপান্তরটি আপনার ডেভেলপমেন্ট প্ল্যাটফর্ম থেকে স্বাধীন এবং আপনি যে কোডটি লিখছেন তা ইডিওম্যাটিক কোটলিন কিনা তা নিশ্চিত করতে সাহায্য করে।
ইডিওম্যাটিক কোটলিন লেখার কোড সংক্ষিপ্ত এবং মিষ্টি করে তোলে। Kotlin প্রদান করে সমস্ত বৈশিষ্ট্য সহ, আপনার কোডকে নিরাপদ, আরও সংক্ষিপ্ত এবং আরও পাঠযোগ্য করার অনেক উপায় রয়েছে৷ উদাহরণস্বরূপ, আমরা init
ব্লক থেকে পরিত্রাণ পেয়ে সরাসরি ঘোষণায় ব্যবহারকারীদের সাথে _users
তালিকাটি ইনস্ট্যান্টিয়েট করে আমাদের Repository
শ্রেণীটি অপ্টিমাইজ করতে পারি:
private val users = mutableListOf(User("Jane", ""), User("John", null), User("Anne", "Doe"))
আমরা শূন্যতা, এককটন, স্ট্রিংস এবং সংগ্রহগুলি পরিচালনা করা থেকে শুরু করে এক্সটেনশন ফাংশন, শীর্ষ-স্তরের ফাংশন, বৈশিষ্ট্য এবং স্কোপ ফাংশনগুলির মতো বিষয়গুলিকে কভার করেছি৷ আমরা দুটি জাভা ক্লাস থেকে দুটি কোটলিনে গিয়েছিলাম যা এখন দেখতে এইরকম:
User.kt
data class User(var firstName: String?, var lastName: String?)
Repository.kt
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 এবং কোটলিনে তাদের ম্যাপিং রয়েছে:
জাভা | কোটলিন |
| |
| |
| |
ক্লাস যে শুধু ডাটা ধারণ করে | |
কনস্ট্রাক্টরে সূচনা | |
| একটি |
সিঙ্গেলটন ক্লাস | |
কোটলিন সম্পর্কে আরও জানতে এবং কীভাবে এটি আপনার প্ল্যাটফর্মে ব্যবহার করবেন, এই সংস্থানগুলি দেখুন: