(বঞ্চিত) কোটলিনে রূপান্তর করা হচ্ছে

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 রূপান্তরের পরে সংশোধনের জন্য অনুরোধ করে, হ্যাঁ টিপুন।

e6f96eace5dabe5f.png

আপনি নিম্নলিখিত 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 । এটি করার জন্য, আমরা শুধু lastNamenull বরাদ্দ করি।

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 ) থাকতে পারে এবং একটি মান ফেরত দিতে পারে।

প্রতিটি ফাংশন কখন ব্যবহার করতে হবে তা মনে রাখতে সাহায্য করার জন্য এখানে একটি সহজ চিট শীট রয়েছে:

6b9283d411fb6e7b.png

যেহেতু আমরা আমাদের 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 এবং কোটলিনে তাদের ম্যাপিং রয়েছে:

জাভা

কোটলিন

final বস্তু

val বস্তু

equals()

==

==

===

ক্লাস যে শুধু ডাটা ধারণ করে

data ক্লাস

কনস্ট্রাক্টরে সূচনা

init ব্লকে সূচনা

static ক্ষেত্র এবং ফাংশন

একটি companion object ঘোষিত ক্ষেত্র এবং ফাংশন

সিঙ্গেলটন ক্লাস

object

কোটলিন সম্পর্কে আরও জানতে এবং কীভাবে এটি আপনার প্ল্যাটফর্মে ব্যবহার করবেন, এই সংস্থানগুলি দেখুন: