কোটলিন-জাভা ইন্টারপ গাইড

এই নথিটি জাভা এবং কোটলিনে পাবলিক API-এর প্রণয়নের জন্য নিয়মের একটি সেট এই উদ্দেশ্য যে কোডটি অন্য ভাষা থেকে ব্যবহার করার সময় বাজে মনে হবে।

শেষ আপডেট: 2024-07-29

জাভা (কোটলিন ব্যবহারের জন্য)

কোন হার্ড কীওয়ার্ড নেই

পদ্ধতি বা ক্ষেত্রের নাম হিসাবে Kotlin এর কোনো কঠিন কীওয়ার্ড ব্যবহার করবেন না। কোটলিন থেকে কল করার সময় এগুলি থেকে বাঁচতে ব্যাকটিক্স ব্যবহার করা প্রয়োজন। সফট কীওয়ার্ড , মডিফায়ার কীওয়ার্ড এবং বিশেষ শনাক্তকারী অনুমোদিত।

উদাহরণস্বরূপ, মকিটোর when কোটলিন থেকে ব্যবহার করার সময় ফাংশনের জন্য ব্যাকটিক্সের প্রয়োজন হয়:

val callable = Mockito.mock(Callable::class.java)
Mockito.`when`(callable.call()).thenReturn(/* … */)

Any এক্সটেনশন নাম এড়িয়ে চলুন

একেবারে প্রয়োজনীয় না হলে Any for methods-এ এক্সটেনশন ফাংশনের নাম বা Any for field-এ এক্সটেনশন বৈশিষ্ট্যের নাম ব্যবহার করা এড়িয়ে চলুন। যদিও সদস্য পদ্ধতি এবং ক্ষেত্রগুলি Any এক্সটেনশন ফাংশন বা বৈশিষ্ট্যগুলির উপর সর্বদা অগ্রাধিকার পাবে, কোডটি পড়ার সময় কোনটিকে বলা হচ্ছে তা জানা কঠিন হতে পারে।

শূন্যতা টীকা

একটি পাবলিক API-এ প্রতিটি নন-প্রিমিটিভ প্যারামিটার, রিটার্ন এবং ফিল্ড টাইপের একটি শূন্যতা টীকা থাকা উচিত। অ-টীকাযুক্ত প্রকারগুলিকে "প্ল্যাটফর্ম" প্রকার হিসাবে ব্যাখ্যা করা হয়, যার অস্পষ্ট শূন্যতা রয়েছে।

ডিফল্টরূপে, Kotlin কম্পাইলার পতাকা JSR 305 টীকাকে সম্মান করে কিন্তু সতর্কতা সহ পতাকা দেয়। আপনি একটি পতাকা সেট করতে পারেন যাতে কম্পাইলার টিকাগুলিকে ত্রুটি হিসাবে বিবেচনা করে।

Lambda পরামিতি শেষ

SAM রূপান্তরের জন্য যোগ্য প্যারামিটার প্রকারগুলি শেষ হওয়া উচিত।

উদাহরণস্বরূপ, RxJava 2-এর Flowable.create() পদ্ধতি স্বাক্ষরকে সংজ্ঞায়িত করা হয়েছে:

public static <T> Flowable<T> create(
    FlowableOnSubscribe<T> source,
    BackpressureStrategy mode) { /* … */ }

যেহেতু FlowableOnSubscribe SAM রূপান্তরের জন্য যোগ্য, Kotlin থেকে এই পদ্ধতির ফাংশন কলগুলি এইরকম দেখায়:

Flowable.create({ /* … */ }, BackpressureStrategy.LATEST)

যদি প্যারামিটারগুলি পদ্ধতি স্বাক্ষরে বিপরীত হয়, যদিও, ফাংশন কলগুলি ট্রেলিং-ল্যাম্বডা সিনট্যাক্স ব্যবহার করতে পারে:

Flowable.create(BackpressureStrategy.LATEST) { /* … */ }

সম্পত্তি উপসর্গ

কোটলিনে একটি সম্পত্তি হিসাবে উপস্থাপন করার জন্য, কঠোর "বিন"-শৈলী উপসর্গ ব্যবহার করা আবশ্যক।

অ্যাক্সেসর পদ্ধতিতে একটি get প্রিফিক্স প্রয়োজন বা বুলিয়ান-রিটার্নিং পদ্ধতির জন্য একটি is ব্যবহার করা যেতে পারে।

public final class User {
  public String getName() { /* … */ }
  public boolean isActive() { /* … */ }
}
val name = user.name // Invokes user.getName()
val active = user.isActive // Invokes user.isActive()

সংযুক্ত মিউটেটর পদ্ধতির জন্য একটি set উপসর্গ প্রয়োজন।

public final class User {
  public String getName() { /* … */ }
  public void setName(String name) { /* … */ }
  public boolean isActive() { /* … */ }
  public void setActive(boolean active) { /* … */ }
}
user.name = "Bob" // Invokes user.setName(String)
user.isActive = true // Invokes user.setActive(boolean)

আপনি যদি পদ্ধতিগুলিকে বৈশিষ্ট্য হিসাবে প্রকাশ করতে চান তবে অ-মানক উপসর্গ যেমন has , set বা non- get -prefixed accessors ব্যবহার করবেন না। অ-মানক উপসর্গ সহ পদ্ধতিগুলি এখনও ফাংশন হিসাবে কলযোগ্য, যা পদ্ধতির আচরণের উপর নির্ভর করে গ্রহণযোগ্য হতে পারে।

অপারেটর ওভারলোডিং

বিশেষ কল-সাইট সিনট্যাক্স (যেমন কোটলিনে অপারেটর ওভারলোডিং ) মঞ্জুরি দেয় এমন পদ্ধতির নাম সম্পর্কে সচেতন থাকুন। নিশ্চিত করুন যে পদ্ধতির নামগুলি সংক্ষিপ্ত সিনট্যাক্সের সাথে ব্যবহার করা অর্থপূর্ণ।

public final class IntBox {
  private final int value;
  public IntBox(int value) {
    this.value = value;
  }
  public IntBox plus(IntBox other) {
    return new IntBox(value + other.value);
  }
}
val one = IntBox(1)
val two = IntBox(2)
val three = one + two // Invokes one.plus(two)

কোটলিন (জাভা ব্যবহারের জন্য)

ফাইলের নাম

যখন একটি ফাইলে শীর্ষ-স্তরের ফাংশন বা বৈশিষ্ট্য থাকে, একটি সুন্দর নাম প্রদান করতে সর্বদা এটি @file:JvmName("Foo") দিয়ে টীকা করুন।

ডিফল্টরূপে, MyClass.kt ফাইলের শীর্ষ-স্তরের সদস্যরা MyClassKt নামক একটি ক্লাসে শেষ হবে যা অপ্রীতিকর এবং একটি বাস্তবায়নের বিবরণ হিসাবে ভাষাটি ফাঁস করে।

একাধিক ফাইল থেকে শীর্ষ-স্তরের সদস্যদের একক শ্রেণিতে একত্রিত করতে @file:JvmMultifileClass যোগ করার কথা বিবেচনা করুন।

ল্যাম্বডা যুক্তি

জাভাতে সংজ্ঞায়িত সিঙ্গেল মেথড ইন্টারফেস (SAM) ল্যাম্বডা সিনট্যাক্স ব্যবহার করে কোটলিন এবং জাভা উভয় ক্ষেত্রেই প্রয়োগ করা যেতে পারে, যা একটি বাগধারায় বাস্তবায়নকে ইনলাইন করে। এই ধরনের ইন্টারফেস সংজ্ঞায়িত করার জন্য কোটলিনের বেশ কয়েকটি বিকল্প রয়েছে, প্রতিটিতে সামান্য পার্থক্য রয়েছে।

পছন্দনীয় সংজ্ঞা

উচ্চ-ক্রম ফাংশনগুলি যা Java থেকে ব্যবহার করা হয় এমন ফাংশন প্রকারগুলি গ্রহণ করা উচিত নয় যা Unit ফেরত দেয় কারণ জাভা কলারদের Unit.INSTANCE ফেরত দিতে হবে। INSTANCE। স্বাক্ষরে ফাংশন টাইপ ইনলাইন করার পরিবর্তে, কার্যকরী (SAM) ইন্টারফেস ব্যবহার করুন। এছাড়াও ল্যাম্বডাস হিসাবে ব্যবহৃত ইন্টারফেসগুলিকে সংজ্ঞায়িত করার সময় নিয়মিত ইন্টারফেসের পরিবর্তে কার্যকরী (SAM) ইন্টারফেসগুলি ব্যবহার করার কথা বিবেচনা করুন, যা Kotlin থেকে মূর্তিপূর্ণ ব্যবহারের অনুমতি দেয়।

এই কোটলিন সংজ্ঞা বিবেচনা করুন:

fun interface GreeterCallback {
  fun greetName(String name)
}

fun sayHi(greeter: GreeterCallback) = /* … */

কোটলিন থেকে আহ্বান করা হলে:

sayHi { println("Hello, $it!") }

যখন জাভা থেকে আহ্বান করা হয়:

sayHi(name -> System.out.println("Hello, " + name + "!"));

এমনকি যখন ফাংশনের ধরন একটি Unit ফেরত না দেয় তখনও এটিকে একটি নামযুক্ত ইন্টারফেস তৈরি করা একটি ভাল ধারণা হতে পারে যাতে কলাররা এটিকে একটি নামযুক্ত শ্রেণির সাথে প্রয়োগ করতে দেয় এবং কেবল ল্যাম্বডাস নয় (কোটলিন এবং জাভা উভয়েই)।

class MyGreeterCallback : GreeterCallback {
  override fun greetName(name: String) {
    println("Hello, $name!");
  }
}

Unit প্রদানকারী ফাংশন প্রকারগুলি এড়িয়ে চলুন

এই কোটলিন সংজ্ঞা বিবেচনা করুন:

fun sayHi(greeter: (String) -> Unit) = /* … */

এটি জাভা কলারদের Unit.INSTANCE ফেরত দিতে হবে। INSTANCE :

sayHi(name -> {
  System.out.println("Hello, " + name + "!");
  return Unit.INSTANCE;
});

কার্যকরী ইন্টারফেস এড়িয়ে চলুন যখন বাস্তবায়নের অবস্থা বোঝানো হয়

যখন ইন্টারফেস বাস্তবায়নের একটি অবস্থা বোঝানো হয়, তখন ল্যাম্বডা সিনট্যাক্স ব্যবহার করার অর্থ হয় না। তুলনাযোগ্য একটি বিশিষ্ট উদাহরণ, কারণ এটি other সাথে this তুলনা করার জন্য বোঝানো হয়েছে, এবং ল্যাম্বডাসের কাছে this নেই। fun সাথে ইন্টারফেসের প্রিফিক্সিং না করা কলারকে object : ... সিনট্যাক্স, যা এটিকে স্টেট থাকতে দেয়, কলারকে একটি ইঙ্গিত দেয়।

এই কোটলিন সংজ্ঞা বিবেচনা করুন:

// No "fun" prefix.
interface Counter {
  fun increment()
}

এটি কোটলিনে ল্যাম্বডা সিনট্যাক্স প্রতিরোধ করে, এই দীর্ঘ সংস্করণের প্রয়োজন:

runCounter(object : Counter {
  private var increments = 0 // State

  override fun increment() {
    increments++
  }
})

জেনেরিক Nothing এড়িয়ে চলুন

একটি টাইপ যার জেনেরিক প্যারামিটার Nothing তা জাভাতে কাঁচা প্রকার হিসাবে উন্মুক্ত হয়। জাভাতে কাঁচা প্রকারগুলি খুব কমই ব্যবহৃত হয় এবং এড়ানো উচিত।

নথির ব্যতিক্রম

যে ফাংশনগুলি চেক করা ব্যতিক্রমগুলি নিক্ষেপ করতে পারে সেগুলিকে @Throws দিয়ে নথিভুক্ত করা উচিত। রানটাইম ব্যতিক্রমগুলি KDoc-এ নথিভুক্ত করা উচিত।

একটি ফাংশন প্রতিনিধিত্বকারী APIগুলি সম্পর্কে সচেতন থাকুন কারণ তারা চেক করা ব্যতিক্রমগুলি নিক্ষেপ করতে পারে যা কোটলিন নীরবে প্রচার করার অনুমতি দেয়।

প্রতিরক্ষামূলক অনুলিপি

যখন পাবলিক API গুলি থেকে শেয়ার করা বা অনাকাক্সিক্ষত পঠন-পাঠন সংগ্রহগুলি ফেরত দেওয়া হয়, তখন সেগুলিকে একটি অপরিবর্তনীয় পাত্রে মোড়ানো বা একটি প্রতিরক্ষামূলক অনুলিপি সম্পাদন করুন৷ কোটলিন তাদের শুধুমাত্র-পঠনযোগ্য সম্পত্তি প্রয়োগ করা সত্ত্বেও, জাভা দিকে এমন কোন প্রয়োগ নেই। মোড়ক বা প্রতিরক্ষামূলক অনুলিপি ব্যতীত, দীর্ঘস্থায়ী সংগ্রহের রেফারেন্স ফিরিয়ে দিয়ে invariants লঙ্ঘন করা যেতে পারে।

সহচর ফাংশন

একটি সহচর বস্তুর পাবলিক ফাংশন একটি স্ট্যাটিক পদ্ধতি হিসাবে উন্মুক্ত করার জন্য @JvmStatic এর সাথে টীকা করা আবশ্যক।

টীকা ছাড়া, এই ফাংশনগুলি শুধুমাত্র একটি স্ট্যাটিক Companion ক্ষেত্রের উদাহরণ পদ্ধতি হিসাবে উপলব্ধ।

ভুল: কোন টীকা নেই

class KotlinClass {
    companion object {
        fun doWork() {
            /* … */
        }
    }
}
public final class JavaClass {
    public static void main(String... args) {
        KotlinClass.Companion.doWork();
    }
}

সঠিক: @JvmStatic টীকা

class KotlinClass {
    companion object {
        @JvmStatic fun doWork() {
            /* … */
        }
    }
}
public final class JavaClass {
    public static void main(String... args) {
        KotlinClass.doWork();
    }
}

সহচর ধ্রুবক

পাবলিক, নন- const বৈশিষ্ট্যগুলি যেগুলি একটি companion object কার্যকর ধ্রুবকগুলিকে একটি স্ট্যাটিক ফিল্ড হিসাবে উন্মুক্ত করার জন্য @JvmField দিয়ে টীকা করতে হবে।

টীকা ব্যতীত, এই বৈশিষ্ট্যগুলি স্ট্যাটিক Companion ক্ষেত্রে শুধুমাত্র অদ্ভুতভাবে নামযুক্ত উদাহরণ "গেটার" হিসাবে উপলব্ধ। @JvmField এর পরিবর্তে @JvmStatic ব্যবহার করা ক্লাসের স্ট্যাটিক পদ্ধতিতে অদ্ভুতভাবে-নামযুক্ত "গেটার" নিয়ে যায়, যা এখনও ভুল।

ভুল: কোন টীকা নেই

class KotlinClass {
    companion object {
        const val INTEGER_ONE = 1
        val BIG_INTEGER_ONE = BigInteger.ONE
    }
}
public final class JavaClass {
    public static void main(String... args) {
        System.out.println(KotlinClass.INTEGER_ONE);
        System.out.println(KotlinClass.Companion.getBIG_INTEGER_ONE());
    }
}

ভুল: @JvmStatic টীকা

class KotlinClass {
    companion object {
        const val INTEGER_ONE = 1
        @JvmStatic val BIG_INTEGER_ONE = BigInteger.ONE
    }
}
public final class JavaClass {
    public static void main(String... args) {
        System.out.println(KotlinClass.INTEGER_ONE);
        System.out.println(KotlinClass.getBIG_INTEGER_ONE());
    }
}

সঠিক: @JvmField টীকা

class KotlinClass {
    companion object {
        const val INTEGER_ONE = 1
        @JvmField val BIG_INTEGER_ONE = BigInteger.ONE
    }
}
public final class JavaClass {
    public static void main(String... args) {
        System.out.println(KotlinClass.INTEGER_ONE);
        System.out.println(KotlinClass.BIG_INTEGER_ONE);
    }
}

ইডিওম্যাটিক নামকরণ

কোটলিনের জাভা থেকে আলাদা কলিং কনভেনশন রয়েছে যা আপনার ফাংশনের নাম পরিবর্তন করতে পারে। নাম ডিজাইন করার জন্য @JvmName ব্যবহার করুন যাতে তারা উভয় ভাষার কনভেনশনের জন্য বা তাদের নিজ নিজ মানক লাইব্রেরির নামকরণের সাথে মেলে।

এটি প্রায়শই এক্সটেনশন ফাংশন এবং এক্সটেনশন বৈশিষ্ট্যগুলির জন্য ঘটে কারণ রিসিভার প্রকারের অবস্থান ভিন্ন।

sealed class Optional<T : Any>
data class Some<T : Any>(val value: T): Optional<T>()
object None : Optional<Nothing>()

@JvmName("ofNullable")
fun <T> T?.asOptional() = if (this == null) None else Some(this)
// FROM KOTLIN:
fun main(vararg args: String) {
    val nullableString: String? = "foo"
    val optionalString = nullableString.asOptional()
}
// FROM JAVA:
public static void main(String... args) {
    String nullableString = "Foo";
    Optional<String> optionalString =
          Optionals.ofNullable(nullableString);
}

ডিফল্টের জন্য ফাংশন ওভারলোড

একটি ডিফল্ট মান থাকা প্যারামিটার সহ ফাংশন অবশ্যই @JvmOverloads ব্যবহার করবে। এই টীকা ছাড়া কোনো ডিফল্ট মান ব্যবহার করে ফাংশনটি চালু করা অসম্ভব।

@JvmOverloads ব্যবহার করার সময়, উত্পন্ন পদ্ধতিগুলি পরীক্ষা করে নিশ্চিত করুন যে সেগুলি প্রতিটি অর্থপূর্ণ। যদি তারা না করে, সন্তুষ্ট না হওয়া পর্যন্ত নিম্নলিখিত রিফ্যাক্টরিংগুলির একটি বা উভয়টি সম্পাদন করুন:

  • শেষের দিকে ডিফল্ট আছে তাদের পছন্দ করতে পরামিতি ক্রম পরিবর্তন করুন।
  • ডিফল্টগুলিকে ম্যানুয়াল ফাংশন ওভারলোডে সরান।

ভুল: কোন @JvmOverloads নেই

class Greeting {
    fun sayHello(prefix: String = "Mr.", name: String) {
        println("Hello, $prefix $name")
    }
}
public class JavaClass {
    public static void main(String... args) {
        Greeting greeting = new Greeting();
        greeting.sayHello("Mr.", "Bob");
    }
}

সঠিক: @JvmOverloads টীকা।

class Greeting {
    @JvmOverloads
    fun sayHello(prefix: String = "Mr.", name: String) {
        println("Hello, $prefix $name")
    }
}
public class JavaClass {
    public static void main(String... args) {
        Greeting greeting = new Greeting();
        greeting.sayHello("Bob");
    }
}

লিন্ট চেক

প্রয়োজনীয়তা

  • অ্যান্ড্রয়েড স্টুডিও সংস্করণ: 3.2 ক্যানারি 10 বা তার পরে
  • অ্যান্ড্রয়েড গ্রেডল প্লাগইন সংস্করণ: 3.2 বা তার পরে

সমর্থিত চেক

এখন অ্যান্ড্রয়েড লিন্ট চেক রয়েছে যা আপনাকে পূর্বে বর্ণিত কিছু আন্তঃব্যবহারের সমস্যা সনাক্ত করতে এবং পতাকাঙ্কিত করতে সহায়তা করবে। জাভাতে শুধুমাত্র সমস্যা (কোটলিন ব্যবহারের জন্য) সনাক্ত করা হয়েছে। বিশেষত, সমর্থিত চেকগুলি হল:

  • অজানা শূন্যতা
  • সম্পত্তি অ্যাক্সেস
  • কোন হার্ড কোটলিন কীওয়ার্ড নেই
  • Lambda পরামিতি শেষ

অ্যান্ড্রয়েড স্টুডিও

এই চেকগুলি সক্ষম করতে, ফাইল > পছন্দ > সম্পাদক > পরিদর্শনে যান এবং কোটলিন ইন্টারঅপারেবিলিটির অধীনে আপনি যে নিয়মগুলি সক্ষম করতে চান তা পরীক্ষা করুন:

চিত্র 1. অ্যান্ড্রয়েড স্টুডিওতে কোটলিন ইন্টারঅপারেবিলিটি সেটিংস।

একবার আপনি যে নিয়মগুলি সক্রিয় করতে চান তা পরীক্ষা করে নিলে, আপনি যখন আপনার কোড পরিদর্শন চালান তখন নতুন চেকগুলি চালানো হবে ( বিশ্লেষণ > কোড পরিদর্শন করুন... )

কমান্ড-লাইন তৈরি করে

কমান্ড-লাইন বিল্ড থেকে এই চেকগুলি সক্রিয় করতে, আপনার build.gradle ফাইলে নিম্নলিখিত লাইনটি যোগ করুন:

গ্রোভি

android {

    ...

    lintOptions {
        enable 'Interoperability'
    }
}

কোটলিন

android {
    ...

    lintOptions {
        enable("Interoperability")
    }
}

lintOptions-এর ভিতরে সমর্থিত কনফিগারেশনের সম্পূর্ণ সেটের জন্য, Android Gradle DSL রেফারেন্স দেখুন।

তারপর, কমান্ড লাইন থেকে ./gradlew lint চালান।