No hay static
palabras clave en Kotlin.
¿Cuál es la mejor manera de representar un static
método Java en Kotlin?
No hay static
palabras clave en Kotlin.
¿Cuál es la mejor manera de representar un static
método Java en Kotlin?
Respuestas:
Coloca la función en el "objeto complementario".
Entonces el código de Java como este:
class Foo {
public static int a() { return 1; }
}
se convertirá
class Foo {
companion object {
fun a() : Int = 1
}
}
Luego puede usarlo desde el código de Kotlin como
Foo.a();
Pero desde el código Java, necesitaría llamarlo como
Foo.Companion.a();
(Que también funciona desde dentro de Kotlin).
Si no le gusta tener que especificar el Companion
bit, puede agregar una @JvmStatic
anotación o nombrar su clase complementaria.
De los documentos :
Objetos acompañantes
Una declaración de objeto dentro de una clase se puede marcar con la palabra clave complementaria:
class MyClass { companion object Factory { fun create(): MyClass = MyClass() } }
Se puede llamar a los miembros del objeto complementario simplemente usando el nombre de la clase como calificador:
val instance = MyClass.create()
...
Sin embargo, en la JVM puede tener miembros de objetos complementarios generados como métodos y campos estáticos reales, si utiliza la
@JvmStatic
anotación. Vea la sección de interoperabilidad de Java para más detalles.
Agregar la @JvmStatic
anotación se ve así
class Foo {
companion object {
@JvmStatic
fun a() : Int = 1;
}
}
y luego existirá como una función estática real de Java, accesible desde Java y Kotlin como Foo.a()
.
Si simplemente no le gusta el Companion
nombre, también puede proporcionar un nombre explícito para el objeto complementario que se ve así:
class Foo {
companion object Blah {
fun a() : Int = 1;
}
}
lo que le permitirá llamarlo desde Kotlin de la misma manera, pero desde java like Foo.Blah.a()
(que también funcionará en Kotlin).
fun a(): Int { return 1 }
o inclusofun a(): Int = 1
fun a() = 1
.
Factory
es el nombre del objeto complementario, pero ¿para qué se puede usar? No tengo idea, pero estaba interesado, así que creé una pregunta dedicada a eso: stackoverflow.com/q/45853459/221955 .
Docs recomienda resolver la mayoría de las necesidades de funciones estáticas con funciones de nivel de paquete . Simplemente se declaran fuera de una clase en un archivo de código fuente. El paquete de un archivo se puede especificar al comienzo de un archivo con la palabra clave package.
Declaración
package foo
fun bar() = {}
Uso
import foo.bar
Alternativamente
import foo.*
Ahora puede llamar a la función con:
bar()
o si no usa la palabra clave de importación:
foo.bar()
Si no especifica el paquete, se podrá acceder a la función desde la raíz.
Si solo tiene experiencia con Java, esto puede parecer un poco extraño. La razón es que kotlin no es un lenguaje estrictamente orientado a objetos. Se podría decir que admite métodos fuera de las clases.
Editar: Han editado la documentación para que ya no incluya la oración sobre recomendar funciones de nivel de paquete. Este es el original al que se hizo referencia anteriormente.
class FooPackage
con todas las propiedades y funciones de nivel superior, y enrutaría todas sus referencias a ellas de manera adecuada. Más información de jetbrains.
bar()
no importa el nombre del archivo, puede nombrarlo BarUtils.kt
o lo que sea, luego, como dice el texto, lo importará conimport <package name>.bar
A. Antigua forma de Java:
Declarar a companion object
para encerrar un método / variable estático
class Foo{
companion object {
fun foo() = println("Foo")
val bar ="bar"
}
}
Utilizar :
Foo.foo() // Outputs Foo
println(Foo.bar) // Outputs bar
B. Nueva forma de Kotlin
Declarar directamente en archivo sin clase en un .kt
archivo.
fun foo() = println("Foo")
val bar ="bar"
Use el methods/variables
con sus nombres . ( Después de importarlos )
Utilizar :
foo() // Outputs Foo
println(bar) // Outputs bar
INSTANCE
palabra clave, como esta:Foo.INSTANCE.sayFoo()
static CLASS
no solo static methdos
. Porque con los objetos complementarios todavía puede crear una instancia de la clase principal.
val
no es estático, es equivalente a static final
en Java
Use el objeto para representar val / var / method para hacer static. Puedes usar object en lugar de singleton class también. Puede usar un compañero si desea hacer estática dentro de una clase
object Abc{
fun sum(a: Int, b: Int): Int = a + b
}
Si necesita llamarlo desde Java:
int z = Abc.INSTANCE.sum(x,y);
En Kotlin, ignore INSTANCE.
object objectName {
fun funName() {
}
}
Debe pasar el objeto complementario para el método estático porque kotlin no tiene una palabra clave estática: se puede llamar a los miembros del objeto complementario simplemente usando el nombre de la clase como calificador:
package xxx
class ClassName {
companion object {
fun helloWord(str: String): String {
return stringValue
}
}
}
Hay 2 formas de aplicar estática en Kotlin
Primero haz un objeto compañero en clase
Por ej .:
class Test{
companion object{
fun isCheck(a:Int):Boolean{
if(a==0) true else false
}
}
}
puedes llamar a esta función como
Test.Companion.isCheck(2)
Otra forma en que podemos usar es hacer una clase de objeto
object Test{
fun isCheck(a:Int):Boolean{
if(a==0) true else false
}
}
¡Feliz codificación!
Test.Companion.isCheck(2)
) IDE muestra advertencias y dice Companion reference is redundant
. Se puede reducir a Test.isCheck(2)
y la forma reducida es más cercana al equivalente de Java.
Kotlin no tiene ninguna palabra clave estática. Usaste eso para Java
class AppHelper {
public static int getAge() {
return 30;
}
}
y para Kotlin
class AppHelper {
companion object {
fun getAge() : Int = 30
}
}
Llamada para Java
AppHelper.getAge();
Llamado para Kotlin
AppHelper.Companion.getAge();
Creo que está funcionando perfectamente.
Me gustaría agregar algo a las respuestas anteriores.
Sí, puede definir funciones en archivos de código fuente (fuera de clase). Pero es mejor si define funciones estáticas dentro de la clase usando Objeto complementario porque puede agregar más funciones estáticas aprovechando las extensiones de Kotlin .
class MyClass {
companion object {
//define static functions here
}
}
//Adding new static function
fun MyClass.Companion.newStaticFunction() {
// ...
}
Y puede llamar a la función definida anteriormente como llamará a cualquier función dentro del Objeto complementario.
A pesar de que esto tiene un poco más de 2 años y tenía muchas respuestas excelentes, estoy viendo algunas otras formas de obtener campos Kotlin "estáticos". Aquí hay una guía de ejemplo para la static
interoperabilidad Kotlin-Java :
Escenario 1: crear un método estático en Kotlin para 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 } }
Java
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); } }
La respuesta de Michael Anderson proporciona más profundidad que esta, y definitivamente debe ser referenciada para este escenario.
Este próximo escenario maneja la creación de campos estáticos en Kotlin para que Java no tenga que seguir llamando KotlinClass.foo()
a aquellos casos en los que no desea una función estática.
Escenario 2: Crear una variable estática en Kotlin para 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 } }
Java
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); } }
Una de las excelentes características de Kotlin es que puede crear funciones y variables de nivel superior. Esto hace que sea mejor crear listas "sin clase" de campos y funciones constantes, que a su vez se pueden usar como static
funciones / campos en Java.
Escenario 3: Acceso a campos y funciones de nivel superior en Kotlin desde 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!") }
Java
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); } }
Otra mención notable que se puede usar en Java como campos "estáticos" son las object
clases de Kotlin . Estas son clases singleton de parámetro cero que se instancian perezosamente en el primer uso. Puede encontrar más información sobre ellos aquí: https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations
Sin embargo, para acceder al singleton, INSTANCE
se crea un objeto especial , que es tan difícil de manejar como lo Companion
es. Aquí se explica cómo usar anotaciones para darle una static
sensación limpia en Java:
Escenario 4: uso de
object
clasesKotlin
@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'?" }
Java
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); } }
Para abreviar, podría usar "objeto complementario" para ingresar al mundo estático de Kotlin como:
companion object {
const val TAG = "tHomeFragment"
fun newInstance() = HomeFragment()
}
y para hacer un campo constante use "const val" como en el código. pero trate de evitar las clases estáticas ya que está dificultando las pruebas unitarias con Mockito !.
La conversión exacta del método estático de Java al equivalente de Kotlin sería así. Por ejemplo, aquí la clase util tiene un método estático que sería equivalente tanto en java como en kotlin. El uso de @JvmStatic es importante.
Código Java:
class Util{
public static String capitalize(String text){
return text.toUpperCase();}
}
Código de Kotlin:
class Util {
companion object {
@JvmStatic
fun capitalize(text:String): String {
return text.toUpperCase()
}
}
}
Simplemente necesita crear un objeto complementario y poner la función en él
class UtilClass {
companion object {
// @JvmStatic
fun repeatIt5Times(str: String): String = str.repeat(5)
}
}
Para invocar el método desde una clase kotlin:
class KotlinClass{
fun main(args : Array<String>) {
UtilClass.repeatIt5Times("Hello")
}
}
o usando importación
import Packagename.UtilClass.Companion.repeatIt5Times
class KotlinClass{
fun main(args : Array<String>) {
repeatIt5Times("Hello")
}
}
Para invocar el método desde una clase java:
class JavaClass{
public static void main(String [] args){
UtilClass.Companion.repeatIt5Times("Hello");
}
}
o agregando @JvmStatic anotación al método
class JavaClass{
public static void main(String [] args){
UtilClass.repeatIt5Times("Hello")
}
}
o ambos agregando @JvmStatic anotación al método y haciendo una importación estática en java
import static Packagename.UtilClass.repeatIt5Times
class JavaClass{
public static void main(String [] args){
repeatIt5Times("Hello")
}
}
Para Java:
public class Constants {
public static final long MAX_CLICK_INTERVAL = 1000;}
Código de Kotlin equivalente:
object Constants {
const val MAX_CLICK_INTERVAL: Long = 1000}
Entonces, para el equivalente de los métodos estáticos de Java, es la clase de objeto en Kotlin.
Para Android usando una cadena de una sola actividad a toda la actividad necesaria. Justo como estática en java
public final static String TEA_NAME = "TEA_NAME";
Enfoque equivalente en 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)
}
}
Otra actividad donde se necesita valor:
val teaName = MainActivity.TEA_NAME
excepto la respuesta de Michael Anderson, tengo codificación con otras dos vías en mi proyecto.
puedes poner en blanco todas las variables a una clase. creó un archivo kotlin llamado Const
object Const {
const val FIRST_NAME_1 = "just"
const val LAST_NAME_1 = "YuMu"
}
Puedes usarlo en kotlin y código java
Log.d("stackoverflow", Const.FIRST_NAME_1)
Puede usar la función de extensión de Kotlin
creado un archivo de Kotlin llamado Ext, debajo del código está el código completo en el archivo Ext
package pro.just.yumu
/**
* Created by lpf on 2020-03-18.
*/
const val FIRST_NAME = "just"
const val LAST_NAME = "YuMu"
Puedes usarlo en el código de Kotlin
Log.d("stackoverflow", FIRST_NAME)
Puedes usarlo en código java
Log.d("stackoverflow", ExtKt.FIRST_NAME);
Escríbalos directamente a los archivos.
En Java (feo):
package xxx;
class XxxUtils {
public static final Yyy xxx(Xxx xxx) { return xxx.xxx(); }
}
En Kotlin:
@file:JvmName("XxxUtils")
package xxx
fun xxx(xxx: Xxx): Yyy = xxx.xxx()
Esos dos códigos se igualan después de la compilación (incluso el nombre del archivo compilado, file:JvmName
se usa para controlar el nombre del archivo compilado, que debe colocarse justo antes de la declaración del nombre del paquete).
Usar @JVMStatic
anotación
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)
}
}
}
Deja, tienes una clase de estudiante . Y tiene un método estático getUniversityName () y un campo estático llamado totalStudent .
Debe declarar el bloque de objetos complementarios dentro de su clase.
companion object {
// define static method & field here.
}
Entonces tu clase se ve como
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
}
}
Entonces puede usar esos métodos estáticos y campos como este.
println("University : " + Student.getUniversityName() + ", Total Student: " + Student.totalStudent)
// Output:
// University : MBSTU, Total Student: 30
No hay una palabra clave estática en kotlin. kotlin docs recomienda usar funciones de nivel de paquete si desea seguir DRY. Cree un archivo con extensión .kt y ponga su método en él.
package p
fun m(){
//fun body
}
después de la compilación m tendrá una firma de vacío final público estático
y
import p.m
☺
Puede lograr la funcionalidad estática en Kotlin by Companion Objects
Un objeto complementario no puede declararse fuera de la clase.
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"
}
}
}
Se puede llamar a los miembros del objeto complementario simplemente usando el nombre de la clase como calificador:
Salida:
MyClass.staticField // This is an example of static field Object Decleration
MyClass.getStaticFunction() : // This is an example of static function for Object Decleration
Mucha gente menciona objetos complementarios, lo cual es correcto. Pero, para que lo sepas, también puedes usar cualquier tipo de objeto (usando la palabra clave del objeto, no la clase), es decir,
object StringUtils {
fun toUpper(s: String) : String { ... }
}
Úselo como cualquier método estático en java:
StringUtils.toUpper("foobar")
Sin embargo, ese tipo de patrón es inútil en Kotlin, una de sus fortalezas es que elimina la necesidad de clases llenas de métodos estáticos. Es más apropiado utilizar funciones globales, de extensión y / o locales en su lugar, dependiendo de su caso de uso. Cuando trabajo, a menudo definimos las funciones de extensión global en un archivo plano separado con la convención de nomenclatura: [className] Extensions.kt, es decir, FooExtensions.kt. Pero más típicamente escribimos funciones donde se necesitan dentro de su clase u objeto operativo.
En Java, podemos escribir de la siguiente manera
class MyClass {
public static int myMethod() {
return 1;
}
}
En Kotlin, podemos escribir de la siguiente manera
class MyClass {
companion object {
fun myMethod() : Int = 1
}
}
un compañero se usa como estático en Kotlin.
El proveedor de documentos de Kotlin tiene tres formas de hacerlo, la primera es definir la función en el paquete, sin clase:
package com.example
fun f() = 1
el segundo es usar la anotación @JvmStatic:
package com.example
class A{
@JvmStatic
fun f() = 1
}
y el tercero es usar objeto complementario:
package com.example
clss A{
companion object{
fun f() = 1
}
}
Si necesita que una función o una propiedad esté vinculada a una clase en lugar de a instancias de ella, puede declararla dentro de un objeto complementario:
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
}
}
}
El objeto complementario es un singleton, y se puede acceder a sus miembros directamente a través del nombre de la clase que lo contiene
val car = Car.makeCar(150)
println(Car.Factory.cars.size)
Puedes usar objetos complementarios - kotlinlang
Que se puede mostrar creando primero esa interfaz
interface I<T> {
}
Luego tenemos que hacer una función dentro de esa interfaz:
fun SomeFunc(): T
Luego, después, necesitamos una clase:
class SomeClass {}
dentro de esa clase necesitamos un objeto compañero dentro de esa clase:
companion object : I<SomeClass> {}
dentro de ese Objeto Compañero necesitamos esa vieja SomeFunc
función, pero necesitamos anularla:
override fun SomeFunc(): SomeClass = SomeClass()
Finalmente, debajo de todo ese trabajo, necesitamos algo para impulsar esa función estática, necesitamos una variable:
var e:I<SomeClass> = SomeClass()