อะไรคือสิ่งที่เทียบเท่าของวิธีการแบบคงที่ Java ใน Kotlin?


619

ไม่มีstaticคำหลักใน Kotlin

วิธีที่ดีที่สุดในการเป็นตัวแทนของstaticวิธีการจาวาใน Kotlin คืออะไร?


8
ใช้ฟังก์ชั่นแพคเกจระดับ
ฟีนิกซ์

12
ได้รับคำแนะนำ: Kotlin ได้ลบ statics สไตล์ Java เพื่อส่งเสริมการบำรุงรักษามากขึ้น (กล้าฉันพูด 'ดีกว่า') การเข้ารหัส รูปทรงกลมคงที่โดยทั่วไปนั้นเทียบกับกระบวนทัศน์ของ OOP แต่มันค่อนข้างสะดวก ดังนั้น Kotlin ทำให้เรามีสหายเป็นวิธีที่เป็นมิตรกับ OOP มากขึ้นของการมีสถิตยศาสตร์
นิโคลัสมิลเลอร์

ตอนนี้ Kotlin เป็นภาษาที่ต้องการสำหรับการพัฒนา Android ตามที่ Google
AFD

@NicholasMiller ทำไมมันถึงเป็นมิตรกับ OOP มากกว่านี้? ฉันคิดว่าการอ่านและเขียนง่ายกว่าโดยไม่มีการบันทึกซ้ำ (คงที่) หรือมีอีกเหตุผลที่ดี?
Torben G

คำตอบ:


888

คุณวางฟังก์ชันใน "วัตถุที่เป็นคู่หู"

ดังนั้นรหัส java เช่นนี้:

class Foo {
  public static int a() { return 1; }
}

จะกลายเป็น

class Foo {
  companion object {
     fun a() : Int = 1
  }
}

จากนั้นคุณสามารถใช้งานได้จากภายในโค้ด Kotlin เป็น

Foo.a();

แต่จากภายในโค้ด Java คุณจะต้องเรียกมันว่า

Foo.Companion.a();

(ซึ่งยังใช้งานได้จากภายใน Kotlin)

หากคุณไม่ต้องการระบุCompanionบิตคุณสามารถเพิ่ม@JvmStaticคำอธิบายประกอบหรือตั้งชื่อคลาสสหายของคุณ

จากเอกสาร :

วัตถุร่วม

การประกาศวัตถุภายในชั้นเรียนสามารถทำเครื่องหมายด้วยคำหลักสหาย:

class MyClass {
   companion object Factory {
       fun create(): MyClass = MyClass()
   }
}

สมาชิกของวัตถุที่แสดงร่วมสามารถเรียกได้โดยใช้ชื่อคลาสเป็นตัวระบุ:

val instance = MyClass.create()

...

อย่างไรก็ตามใน JVM คุณสามารถมีสมาชิกของออบเจกต์ร่วมที่สร้างขึ้นเป็นวิธีการและฟิลด์แบบสแตติกจริงหากคุณใช้@JvmStatic หมายเหตุประกอบ ดูที่ส่วนการทำงานร่วมกันของ Java สำหรับรายละเอียดเพิ่มเติม

การเพิ่ม@JvmStaticคำอธิบายประกอบจะมีลักษณะดังนี้

class Foo {
  companion object {
    @JvmStatic
    fun a() : Int = 1;
  }
}

แล้วมันจะอยู่เป็นจริงฟังก์ชั่น Java คงสามารถเข้าถึงได้จากทั้ง Java และ Kotlin Foo.a()เป็น

หากไม่ชอบCompanionชื่อคุณก็สามารถระบุชื่อที่ชัดเจนให้กับวัตถุที่แสดงร่วมเช่นนี้:

class Foo {
  companion object Blah {
    fun a() : Int = 1;
  }
}

ซึ่งจะให้คุณโทรจาก Kotlin ด้วยวิธีเดียวกัน แต่จาก java like Foo.Blah.a()(ซึ่งจะทำงานใน Kotlin ด้วย)


4
ใน Kotlin มันจะเป็นfun a(): Int { return 1 }หรือแม้กระทั่งfun a(): Int = 1
Dmitry Zaytsev

3
@DmitryZaitsev หรือfun a() = 1แม้กระทั่ง
Moira

โรงงานหมายความว่าอย่างไร
Bagus Aji Santoso

@BagusAjiSantoso Factoryเป็นชื่อของวัตถุร่วม - แต่สิ่งที่สามารถนำมาใช้เพื่อ? ฉันมีความคิด แต่ผมมีความสนใจดังนั้นฉันสร้างคำถามที่ทุ่มเทให้กับว่าstackoverflow.com/q/45853459/221955
Michael Anderson

1
@ Yajairo87 ฉันคิดว่าสิ่งที่คุณถามมีมากเกินกว่าที่จะครอบคลุมในความคิดเห็นได้ที่นี่ - ดังนั้นฉันจึงได้สร้างคำถามขึ้นมาโดยตรง: stackoverflow.com/questions/47046474/…
Michael Anderson

154

เอกสารแนะนำการแก้ปัญหาส่วนใหญ่ของความต้องการสำหรับการทำงานคงที่ที่มีฟังก์ชั่นแพคเกจระดับ พวกมันถูกประกาศนอกคลาสในไฟล์ซอร์สโค้ด แพ็คเกจของไฟล์สามารถระบุได้ที่จุดเริ่มต้นของไฟล์ด้วยคีย์เวิร์ดของแพ็กเกจ

การประกาศ

package foo

fun bar() = {}

การใช้

import foo.bar

อีกทางเลือกหนึ่ง

import foo.*

ตอนนี้คุณสามารถเรียกใช้ฟังก์ชันด้วย:

bar()

หรือถ้าคุณไม่ใช้คำสำคัญที่นำเข้า:

foo.bar()

หากคุณไม่ได้ระบุแพ็คเกจฟังก์ชันจะสามารถเข้าถึงได้จากรูท

หากคุณมีประสบการณ์กับจาวาเพียงอย่างเดียวนี่อาจดูแปลกไปหน่อย เหตุผลคือ kotlin ไม่ใช่ภาษาเชิงวัตถุอย่างเคร่งครัด คุณสามารถพูดได้ว่ามันรองรับวิธีการนอกชั้นเรียน

แก้ไข: พวกเขาได้แก้ไขเอกสารเพื่อไม่รวมประโยคเกี่ยวกับการแนะนำฟังก์ชั่นระดับแพ็คเกจ นี่คือต้นฉบับที่อ้างถึงข้างต้น


8
โปรดทราบว่าภายใต้ประทุนฟังก์ชั่น "ระดับสูงสุด" หรือ "แพ็คเกจ" เหล่านี้จะถูกรวบรวมไว้ในชั้นเรียนของตนเอง ในตัวอย่างด้านบนคอมไพเลอร์จะสร้างclass FooPackageคุณสมบัติและฟังก์ชันระดับบนทั้งหมดและกำหนดเส้นทางการอ้างอิงทั้งหมดของคุณอย่างเหมาะสม ข้อมูลเพิ่มเติมจาก jetbrains
Mitchell Tracy

29
+1 สำหรับการอธิบายวิธีการทำสิ่งที่ถูกต้องใน Kotlinมากกว่าเพียงแค่การเทียบเท่ากระจกเงาจาก Java
ฟีนิกซ์

1
นี่ควรเป็นคำตอบที่ได้รับการยอมรับหรือ mod ควรปรับปรุงคำตอบที่ยอมรับเพื่อให้มีฟังก์ชั่นระดับแพ็คเกจ
Osama Shabrez

@MitchellTracy บิตของข้อมูลที่ยอดเยี่ยม! ขอบคุณ
Droid

1
นี่คือทางออกที่ดีกว่า แค่ต้องการชี้แจงว่าที่คุณกำหนดฟังก์ชั่นbar()ไม่สำคัญว่าชื่อไฟล์คุณสามารถตั้งชื่อBarUtils.ktหรืออะไรก็ตามเมื่อข้อความบอกว่าคุณจะนำเข้ามันด้วยimport <package name>.bar
Mariano Ruiz

33

A. ทางจาวาเก่า:

  1. ประกาศ a companion objectเพื่อใส่เมธอด / ตัวแปรแบบสแตติก

    class Foo{
    companion object {
        fun foo() = println("Foo")
        val bar ="bar"  
        }
    }
  2. การใช้:

    Foo.foo()        // Outputs Foo    
    println(Foo.bar) // Outputs bar


B. วิธี Kotlin ใหม่

  1. ประกาศโดยตรงบนไฟล์โดยไม่มีคลาสบน.ktไฟล์

    fun foo() = println("Foo")
    val bar ="bar"
  2. ใช้methods/variablesกับของพวกเขาชื่อ ( หลังจากนำเข้า )

    ใช้:

    foo()        // Outputs Foo          
    println(bar) // Outputs bar     


ถ้าฉันพยายามที่จะเริ่มต้นในชั้นอื่น ๆ มันให้ java.lang.ExceptionInInialializerError และฉัน m ใช้ var แทน val
Sudarshan

4
การเรียกใช้วิธีต้องมีINSTANCEคำหลักเช่นนี้:Foo.INSTANCE.sayFoo()
Raeglan

ผมคิดว่าวิธีนี้เป็นวิธีที่ต้องการถ้าคุณต้องการไม่เพียงstatic CLASS static methdosเพราะด้วยวัตถุที่เป็นเพื่อนคุณยังสามารถสร้างอินสแตนซ์ของคลาส parent ได้
fabriciorissetto

valไม่คงที่เทียบเท่ากับstatic finalใน Java
Farid

23

ใช้วัตถุเพื่อแสดง val / var / method เพื่อสร้างแบบคงที่ คุณสามารถใช้ object แทนคลาส singleton ได้เช่นกัน คุณสามารถใช้คู่หูถ้าคุณต้องการทำให้คงที่ภายในชั้นเรียน

object Abc{
     fun sum(a: Int, b: Int): Int = a + b
    }

หากคุณต้องการโทรจาก Java:

int z = Abc.INSTANCE.sum(x,y);

ใน Kotlin ไม่สนใจ INSTANCE



8
object objectName {
    fun funName() {

    }
}

5
ในขณะที่ข้อมูลโค้ดนี้อาจเป็นโซลูชันรวมถึงคำอธิบายช่วยปรับปรุงคุณภาพการโพสต์ของคุณ จำไว้ว่าคุณกำลังตอบคำถามสำหรับผู้อ่านในอนาคตและคนเหล่านั้นอาจไม่ทราบสาเหตุของการแนะนำรหัสของคุณ
Narendra Jadhav

5

คุณต้องส่งวัตถุร่วมสำหรับวิธีการคงที่เพราะ kotlin ไม่มีคำหลักคงที่ - สมาชิกของวัตถุสหายสามารถเรียกได้โดยใช้ชื่อคลาสเป็นตัวระบุ:

package xxx
    class ClassName {
              companion object {
                       fun helloWord(str: String): String {
                            return stringValue
                      }
              }
    }

4

มี 2 ​​วิธีที่คุณสามารถใช้แบบคงที่ใน Kotlin

ก่อนอื่นให้สร้างวัตถุร่วมภายใต้ชั้นเรียน

ตัวอย่างเช่น:

class Test{
    companion object{
          fun isCheck(a:Int):Boolean{
             if(a==0) true else false
          }
     }
}

คุณสามารถเรียกใช้ฟังก์ชั่นนี้เป็น

Test.Companion.isCheck(2)

อีกวิธีที่เราสามารถใช้คือการสร้างคลาสวัตถุ

object Test{
       fun isCheck(a:Int):Boolean{
            if(a==0) true else false
       }
}

Happy Coding!


สำหรับการใช้งานครั้งแรก (คือTest.Companion.isCheck(2)) IDE Companion reference is redundantคำเตือนการแสดงและการพูด มันสามารถลดลงได้Test.isCheck(2)และรูปแบบที่ลดลงจะใกล้เคียงกับ java เทียบเท่า
VSB

3

Kotlin ไม่มีคำหลักคงที่ใด ๆ คุณใช้มันสำหรับจาวา

 class AppHelper {
        public static int getAge() {
            return 30;
        }
    }

และสำหรับ Kotlin

class AppHelper {
        companion object {
            fun getAge() : Int = 30
        }
    }

โทรหาจาวา

AppHelper.getAge();

โทรหา Kotlin

AppHelper.Companion.getAge();

ฉันคิดว่ามันทำงานได้อย่างสมบูรณ์


3

ฉันต้องการจะเพิ่มคำตอบข้างบน

ใช่คุณสามารถกำหนดฟังก์ชั่นในไฟล์ซอร์สโค้ด (นอกคลาส) แต่มันจะดีกว่าถ้าคุณกำหนดฟังก์ชั่นแบบคงที่ภายในชั้นเรียนโดยใช้วัตถุ Companionเพราะคุณสามารถเพิ่มฟังก์ชั่นแบบคงที่มากขึ้นโดยการใช้ประโยชน์จากKotlin ส่วนขยาย

class MyClass {
    companion object { 
        //define static functions here
    } 
}

//Adding new static function
fun MyClass.Companion.newStaticFunction() {
    // ...
}

และคุณสามารถเรียกใช้ฟังก์ชันที่กำหนดไว้ข้างต้นได้เนื่องจากคุณจะเรียกใช้ฟังก์ชันใด ๆ ภายในวัตถุที่แสดงร่วม


3

แม้ว่าตอนนี้จะมีอายุมากกว่า 2 ปีและมีคำตอบมากมาย แต่ฉันก็เห็นวิธีอื่น ๆ ในการรับฟิลด์ "คงที่" Kotlin หายไป นี่คือคำแนะนำตัวอย่างสำหรับ Kotlin-Java staticinterop:

สถานการณ์ที่ 1: การสร้างวิธีการคงที่ใน Kotlin สำหรับ Java

Kotlin

@file:JvmName("KotlinClass") //This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Java
package com.frybits

class KotlinClass {
    companion object {

        //This annotation tells Java classes to treat this method as if it was a static to [KotlinClass]
        @JvmStatic
        fun foo(): Int = 1

        //Without it, you would have to use [KotlinClass.Companion.bar()] to use this method.
        fun bar(): Int = 2
    }
}

ชวา

package com.frybits;

class JavaClass {

    void someFunction() {
        println(KotlinClass.foo()); //Prints "1"
        println(KotlinClass.Companion.bar()); //Prints "2". This is the only way to use [bar()] in Java.
        println(KotlinClass.Companion.foo()); //To show that [Companion] is still the holder of the function [foo()]
    }

    //Because I'm way to lazy to keep typing [System.out], but I still want this to be compilable.
    void println(Object o) {
        System.out.println(o);
    }
}

คำตอบของ Michael Anderson ให้ความลึกมากกว่านี้และควรอ้างอิงสำหรับสถานการณ์นี้อย่างแน่นอน


สถานการณ์จำลองถัดไปนี้จัดการการสร้างฟิลด์สแตติกใน Kotlin เพื่อให้ Java ไม่จำเป็นต้องโทรKotlinClass.foo()หาเคสที่คุณไม่ต้องการฟังก์ชั่นสแตติก

สถานการณ์ที่ 2: การสร้างตัวแปรแบบคงที่ใน Kotlin สำหรับ Java

Kotlin

@file:JvmName("KotlinClass") //This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Java
package com.frybits

class KotlinClass {

    companion object {

        //This annotation tells Kotlin to not generate the getter/setter functions in Java. Instead, this variable should be accessed directly
        //Also, this is similar to [@JvmStatic], in which it tells Java to treat this as a static variable to [KotlinClass].
        @JvmField
        var foo: Int = 1

        //If you want something akin to [final static], and the value is a primitive or a String, you can use the keyword [const] instead
        //No annotation is needed to make this a field of [KotlinClass]. If the declaration is a non-primitive/non-String, use @JvmField instead
        const val dog: Int = 1

        //This will be treated as a member of the [Companion] object only. It generates the getter/setters for it.
        var bar: Int = 2

        //We can still use [@JvmStatic] for 'var' variables, but it generates getter/setters as functions of KotlinClass
        //If we use 'val' instead, it only generates a getter function
        @JvmStatic
        var cat: Int = 9
    }
}

ชวา

package com.frybits;

class JavaClass {

    void someFunction() {
        //Example using @JvmField
        println(KotlinClass.foo); //Prints "1"
        KotlinClass.foo = 3;

        //Example using 'const val'
        println(KotlinClass.dog); //Prints "1". Notice the lack of a getter function

        //Example of not using either @JvmField, @JvmStatic, or 'const val'
        println(KotlinClass.Companion.getBar()); //Prints "2"
        KotlinClass.Companion.setBar(3); //The setter for [bar]

        //Example of using @JvmStatic instead of @JvmField
        println(KotlinClass.getCat());
        KotlinClass.setCat(0);
    }

    void println(Object o) {
        System.out.println(o);
    }
}

หนึ่งในคุณสมบัติที่ยอดเยี่ยมเกี่ยวกับ Kotlin คือคุณสามารถสร้างฟังก์ชั่นและตัวแปรระดับบนสุด สิ่งนี้ทำให้เกิดความปรารถนาในการสร้างรายการ "classless" ของเขตข้อมูลและฟังก์ชันคงที่ซึ่งสามารถใช้เป็นstaticฟังก์ชัน / เขตข้อมูลใน Java

สถานการณ์จำลอง 3: การเข้าถึงฟิลด์และฟังก์ชันระดับสูงสุดใน Kotlin จาก Java

Kotlin

//In this example, the file name is "KSample.kt". If this annotation wasn't provided, all functions and fields would have to accessed
//using the name [KSampleKt.foo()] to utilize them in Java. Make life easier for yourself, and name this something more simple
@file:JvmName("KotlinUtils")

package com.frybits

//This can be called from Java as [KotlinUtils.TAG]. This is a final static variable
const val TAG = "You're it!"

//Since this is a top level variable and not part of a companion object, there's no need to annotate this as "static" to access in Java.
//However, this can only be utilized using getter/setter functions
var foo = 1

//This lets us use direct access now
@JvmField
var bar = 2

//Since this is calculated at runtime, it can't be a constant, but it is still a final static variable. Can't use "const" here.
val GENERATED_VAL:Long = "123".toLong()

//Again, no need for @JvmStatic, since this is not part of a companion object
fun doSomethingAwesome() {
    println("Everything is awesome!")
}

ชวา

package com.frybits;

class JavaClass {

    void someFunction() {

        println(KotlinUtils.TAG); //Example of printing [TAG]


        //Example of not using @JvmField.
        println(KotlinUtils.getFoo()); //Prints "1"
        KotlinUtils.setFoo(3);

        //Example using @JvmField
        println(KotlinUtils.bar); //Prints "2". Notice the lack of a getter function
        KotlinUtils.bar = 3;

        //Since this is a top level variable, no need for annotations to use this
        //But it looks awkward without the @JvmField
        println(KotlinUtils.getGENERATED_VAL());

        //This is how accessing a top level function looks like
        KotlinUtils.doSomethingAwesome();
    }

    void println(Object o) {
        System.out.println(o);
    }
}

การกล่าวถึงที่น่าสังเกตอีกประการหนึ่งที่สามารถใช้ใน Java เป็นเขตข้อมูล "คงที่" คือobjectคลาสKotlin เหล่านี้เป็นพารามิเตอร์ศูนย์เดี่ยวชั้นเรียนที่มีอินสแตนซ์ขี้เกียจเมื่อใช้ครั้งแรก ข้อมูลเพิ่มเติมเกี่ยวกับพวกเขาสามารถพบได้ที่นี่: https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations

อย่างไรก็ตามในการเข้าถึงซิงเกิลINSTANCEนั้นจะมีการสร้างวัตถุพิเศษซึ่งยุ่งยากในการจัดการตามที่เป็นCompanionอยู่ ต่อไปนี้เป็นวิธีใช้คำอธิบายประกอบเพื่อให้staticความรู้สึกสะอาดใน Java:

สถานการณ์ที่ 4: การใช้objectคลาส

Kotlin

@file:JvmName("KotlinClass")

//This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Java
package com.frybits

object KotlinClass { //No need for the 'class' keyword here.

    //Direct access to this variable
    const val foo: Int = 1

    //Tells Java this can be accessed directly from [KotlinClass]
    @JvmStatic
    var cat: Int = 9

    //Just a function that returns the class name
    @JvmStatic
    fun getCustomClassName(): String = this::class.java.simpleName + "boo!"

    //Getter/Setter access to this variable, but isn't accessible directly from [KotlinClass]
    var bar: Int = 2

    fun someOtherFunction() = "What is 'INSTANCE'?"
}

ชวา

package com.frybits;

class JavaClass {

    void someFunction() {
        println(KotlinClass.foo); //Direct read of [foo] in [KotlinClass] singleton

        println(KotlinClass.getCat()); //Getter of [cat]
        KotlinClass.setCat(0); //Setter of [cat]

        println(KotlinClass.getCustomClassName()); //Example of using a function of this 'object' class

        println(KotlinClass.INSTANCE.getBar()); //This is what the singleton would look like without using annotations
        KotlinClass.INSTANCE.setBar(23);

        println(KotlinClass.INSTANCE.someOtherFunction()); //Accessing a function in the object class without using annotations
    }

    void println(Object o) {
        System.out.println(o);
    }
}

3

เพื่อให้สั้นคุณสามารถใช้"วัตถุร่วม"เพื่อเข้าสู่โลกคงที่ Kotlin เช่น:

  companion object {
    const val TAG = "tHomeFragment"
    fun newInstance() = HomeFragment()
}

และเพื่อให้ฟิลด์คงที่ให้ใช้"const val"ดังในรหัส แต่พยายามหลีกเลี่ยงคลาสสแตติกเนื่องจากมันสร้างปัญหาในการทดสอบหน่วยโดยใช้ Mockito!


3

การแปลงที่แน่นอนของวิธีการจาวาแบบคงที่เพื่อเทียบเท่า kotlin จะเป็นเช่นนี้ เช่นที่นี่ชั้น util มีวิธีหนึ่งคงที่ซึ่งจะเทียบเท่าทั้งใน java และ kotlin การใช้@JvmStaticเป็นสิ่งสำคัญ

รหัส Java:

    class Util{
         public static String capitalize(String text){
         return text.toUpperCase();}
       }

รหัส Kotlin:

    class Util {
        companion object {
            @JvmStatic
            fun capitalize(text:String): String {
                return text.toUpperCase()
            }
        }
    }

2

เพียงคุณต้องสร้างวัตถุร่วมและวางฟังก์ชันไว้ในนั้น

  class UtilClass {
        companion object {
  //        @JvmStatic
            fun repeatIt5Times(str: String): String = str.repeat(5)
        }
    }

ในการเรียกใช้เมธอดจากคลาส kotlin:

class KotlinClass{
  fun main(args : Array<String>) { 
    UtilClass.repeatIt5Times("Hello")
  }
}

หรือใช้การนำเข้า

import Packagename.UtilClass.Companion.repeatIt5Times
class KotlinClass{
  fun main(args : Array<String>) { 
     repeatIt5Times("Hello")
  }
}

ในการเรียกใช้เมธอดจากคลาส java:

 class JavaClass{
    public static void main(String [] args){
       UtilClass.Companion.repeatIt5Times("Hello");
    }
 }

หรือโดยการเพิ่มคำอธิบายประกอบ @JvmStatic ให้กับวิธีการ

class JavaClass{
   public static void main(String [] args){
     UtilClass.repeatIt5Times("Hello")
   }
}

หรือทั้งสองอย่างโดยการเพิ่มคำอธิบายประกอบ @JvmStatic ให้กับวิธีการและการนำเข้าแบบคงที่ใน java

import static Packagename.UtilClass.repeatIt5Times
class JavaClass{
   public static void main(String [] args){
     repeatIt5Times("Hello")
   }
}

2

สำหรับ Java:

public class Constants {
public static final long MAX_CLICK_INTERVAL = 1000;}

รหัส Kotlin ที่เทียบเท่า:

object  Constants {
const val MAX_CLICK_INTERVAL: Long = 1000}

ดังนั้นสำหรับเทียบเท่าของวิธีการคงที่ Java เป็นระดับวัตถุใน Kotlin


2

สำหรับ Android ที่ใช้สตริงจากกิจกรรมเดียวไปยังกิจกรรมที่จำเป็นทั้งหมด เหมือนสถิตใน java

public final static String TEA_NAME = "TEA_NAME";

วิธีการที่เท่าเทียมกันใน Kotlin:

class MainActivity : AppCompatActivity() {
    companion object {
        const val TEA_NAME = "TEA_NAME"
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

กิจกรรมอื่นที่ต้องการคุณค่า:

val teaName = MainActivity.TEA_NAME

2

ยกเว้นคำตอบของไมเคิลแอนเดอร์สันฉันได้เขียนโค้ดกับอีกสองทางในโครงการของฉัน

ครั้งแรก:

คุณสามารถเปลี่ยนตัวแปรทั้งหมดให้เป็นหนึ่งคลาสได้ สร้างไฟล์ kotlin ชื่อ Const

object Const {
    const val FIRST_NAME_1 = "just"
    const val LAST_NAME_1 = "YuMu"
}

คุณสามารถใช้มันใน kotlin และรหัส java

 Log.d("stackoverflow", Const.FIRST_NAME_1)

ประการที่สอง:

คุณสามารถใช้ฟังก์ชั่นเสริมของ Kotlin
สร้างไฟล์ kotlin ชื่อ Ext, ด้านล่างรหัสเป็นรหัสทั้งหมดในไฟล์ Ext

package pro.just.yumu

/**
 * Created by lpf on 2020-03-18.
 */

const val FIRST_NAME = "just"
const val LAST_NAME = "YuMu"

คุณสามารถใช้มันในรหัส kotlin

 Log.d("stackoverflow", FIRST_NAME)

คุณสามารถใช้มันในโค้ดจาวา

 Log.d("stackoverflow", ExtKt.FIRST_NAME);

1

เขียนโดยตรงไปยังไฟล์

ใน Java (น่าเกลียด):

package xxx;
class XxxUtils {
  public static final Yyy xxx(Xxx xxx) { return xxx.xxx(); }
}

ใน Kotlin:

@file:JvmName("XxxUtils")
package xxx
fun xxx(xxx: Xxx): Yyy = xxx.xxx()

โค้ดสองชิ้นเหล่านั้นมีค่าเท่ากับหลังการคอมไพล์ (แม้แต่ชื่อไฟล์ที่คอมไพล์แล้ว, file:JvmNameใช้เพื่อควบคุมชื่อไฟล์ที่คอมไพล์, ซึ่งควรใส่ก่อนการประกาศชื่อแพ็คเกจ)


7
คุณลืม "Kotlin (น่าเกลียด)" ... KOTLIN: วัตถุร่วม {val handler = วัตถุ: ตัวจัดการ (Looper.getMainLooper ()) {] ..... JAVA: ตัวจัดการแบบคงที่ตัวจัดการ = ตัวจัดการแบบใหม่ (Looper.getMainLooper () ) {};
CmosBattery

1

ใช้@JVMStaticคำอธิบายประกอบ

companion object {

    // TODO: Rename and change types and number of parameters
    @JvmStatic
    fun newInstance(param1: String, param2: String) =
            EditProfileFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_PARAM1, param1)
                    putString(ARG_PARAM2, param2)
                }
            }
}

1

ให้คุณได้เรียนนักศึกษา และคุณมีหนึ่งคงวิธีgetUniversityName ()และหนึ่งคงข้อมูลที่เรียกว่าtotalStudent

คุณควรประกาศบล็อกวัตถุร่วมภายในชั้นเรียนของคุณ

companion object {
 // define static method & field here.
}

จากนั้นชั้นเรียนของคุณดูเหมือน

    class Student(var name: String, var city: String, var rollNumber: Double = 0.0) {

    // use companion object structure
    companion object {

        // below method will work as static method
        fun getUniversityName(): String = "MBSTU"

        // below field will work as static field
        var totalStudent = 30
    }
}

จากนั้นคุณสามารถใช้วิธีการคงที่และฟิลด์เช่นนี้

println("University : " + Student.getUniversityName() + ", Total Student: " + Student.totalStudent)
    // Output:
    // University : MBSTU, Total Student: 30

1

ไม่มีคำหลักคงที่ใน kotlin kotlin docs แนะนำให้ใช้ฟังก์ชั่นระดับแพ็คเกจหากคุณต้องการติดตาม DRY สร้างไฟล์ที่มีนามสกุล. tkและใส่วิธีการของคุณลงไป

package p
    fun m(){
    //fun body
    }

หลังจากรวบรวมmจะมีลายเซ็นของโมฆะสุดท้ายคงที่สาธารณะ

และ

import p.m


0

คุณสามารถบรรลุฟังก์ชั่นคงที่ใน Kotlin โดยCompanion Objects

  • การเพิ่มสหายในการประกาศวัตถุช่วยให้การเพิ่ม คงที่ฟังก์ชันการทำงานให้กับวัตถุแม้ว่าแนวคิดแบบคงที่ที่เกิดขึ้นจริงไม่ได้อยู่ใน Kotlin
  • วัตถุสหายสามารถเข้าถึงสมาชิกทุกคนในชั้นเรียนมากเกินไปรวมทั้งการก่อสร้างภาคเอกชน
  • วัตถุสหายจะเริ่มต้นเมื่อชั้นจะ instantiated
  • วัตถุสหายไม่สามารถประกาศนอกชั้นเรียน

    class MyClass{
    
        companion object {
    
            val staticField = "This is an example of static field Object Decleration"
    
            fun getStaticFunction(): String {
                return "This is example of static function for Object Decleration"
            }
    
        }
    }

สมาชิกของวัตถุที่แสดงร่วมสามารถเรียกได้โดยใช้ชื่อคลาสเป็นตัวระบุ:

เอาท์พุท:

MyClass.staticField // This is an example of static field Object Decleration

MyClass.getStaticFunction() : // This is an example of static function for Object Decleration

0

สมาชิกคงที่และฟังก์ชั่นทั้งหมดควรอยู่ในบล็อกสหาย

  companion object {
    @JvmStatic
    fun main(args: Array<String>) {
    }

    fun staticMethod() {
    }
  }

0

ผู้คนจำนวนมากพูดถึงวัตถุสหายซึ่งถูกต้อง แต่เพื่อให้คุณรู้คุณสามารถใช้วัตถุประเภทใดก็ได้ (โดยใช้คำสำคัญของวัตถุไม่ใช่คลาส) เช่น

object StringUtils {
    fun toUpper(s: String) : String { ... }
}

ใช้มันเหมือนกับวิธีคงที่ใด ๆ ใน java:

StringUtils.toUpper("foobar")

รูปแบบดังกล่าวนั้นไร้ประโยชน์ใน Kotlin แต่จุดแข็งอย่างหนึ่งของมันคือการกำจัดความจำเป็นในการเรียนที่เต็มไปด้วยวิธีการคงที่ มันเหมาะสมกว่าที่จะใช้ฟังก์ชั่นสากลส่วนขยายและ / หรือท้องถิ่นแทนขึ้นอยู่กับกรณีการใช้งานของคุณ ที่ที่ฉันทำงานเรามักจะกำหนดฟังก์ชั่นการขยายแบบโกลบอลในไฟล์ flat แยกต่างหากด้วยหลักการตั้งชื่อ: [className] Extensions.kt ie, FooExtensions.kt แต่โดยทั่วไปแล้วเราเขียนฟังก์ชันที่ต้องการใช้ในคลาสปฏิบัติการหรือวัตถุ


0

ใน Java เราสามารถเขียนในวิธีด้านล่าง

class MyClass {
  public static int myMethod() { 
  return 1;
  }
}

ใน Kotlin เราสามารถเขียนได้ด้านล่าง

class MyClass {
  companion object {
     fun myMethod() : Int = 1
  }
}

สหายถูกใช้เป็นแบบคงที่ใน Kotlin


0

ผู้ให้บริการเอกสาร kotlin สามวิธีในการทำสิ่งแรกคือกำหนดฟังก์ชันในแพ็คเกจโดยไม่มีคลาส:

package com.example

fun f() = 1

ที่สองคือการใช้คำอธิบายประกอบ @JvmStatic:

package com.example

class A{
@JvmStatic
fun f() = 1
}

และที่สามคือการใช้วัตถุสหาย:

package com.example

clss A{
companion object{
fun f() = 1
}
}

-1

หากคุณต้องการฟังก์ชั่นหรือคุณสมบัติที่จะผูกกับคลาสแทนที่จะเป็นอินสแตนซ์ของมันคุณสามารถประกาศมันภายในวัตถุที่เป็นเพื่อนร่วม:

class Car(val horsepowers: Int) {
    companion object Factory {
        val cars = mutableListOf<Car>()

        fun makeCar(horsepowers: Int): Car {
            val car = Car(horsepowers)
            cars.add(car)
            return car
        }
    }
}

วัตถุสหายคือซิงเกิลและสมาชิกสามารถเข้าถึงได้โดยตรงผ่านชื่อของชั้นที่มี

val car = Car.makeCar(150)
println(Car.Factory.cars.size)

ดูเหมือนว่าคำตอบที่ยอมรับแล้วอธิบายวัตถุที่เป็นคู่หูกันแล้ว ดังนั้นคำตอบอื่น ๆ มากมาย คำตอบของคุณมีอะไรใหม่หรือไม่?
Sneftel

สำหรับการชี้แจงเพิ่มเติมคุณสามารถตรวจสอบได้ที่นี่kotlinlang.org/docs/tutorials/kotlin-for-py/ ......
asad mahmood

-2

คุณสามารถใช้วัตถุร่วม - kotlinlang

ซึ่งมันสามารถแสดงได้โดยสร้างอินเทอร์เฟซนั้นก่อน

interface I<T> {

}

จากนั้นเราต้องสร้างฟังก์ชั่นภายในอินเทอร์เฟซนั้น:

fun SomeFunc(): T

หลังจากนั้นเราต้องการคลาส:

class SomeClass {}

ภายในคลาสนั้นเราจำเป็นต้องมี Object สหายภายในคลาสนั้น:

companion object : I<SomeClass> {}

ภายใน Companion Object นั้นเราต้องการSomeFuncฟังก์ชั่นแบบเก่าแต่เราต้องขับมัน:

override fun SomeFunc(): SomeClass = SomeClass()

ในที่สุดด้านล่างของงานทั้งหมดนั้นเราต้องการบางสิ่งบางอย่างเพื่อเพิ่มพลังให้กับฟังก์ชั่นคงที่เราต้องการตัวแปร

var e:I<SomeClass> = SomeClass()
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.