java - objeto - herencia multiple kotlin
¿Cuál es el equivalente de los métodos estáticos de Java en Kotlin? (29)
No hay una palabra clave
static
en Kotlin.
¿Cuál es la mejor manera de representar un método Java
static
en Kotlin?
A pesar de que ahora 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
static
interoperabilidad
static
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.
El siguiente escenario maneja la creación de campos estáticos en Kotlin para que Java no tenga que seguir llamando a
KotlinClass.foo()
para 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 funciones / campos
static
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 utilizar en Java como campos "estáticos" son las clases de
object
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, se crea un objeto
INSTANCE
especial, que es tan engorroso de manejar como
Companion
.
Aquí le mostramos cómo usar anotaciones para darle una sensación
static
limpia en Java:
Escenario 4: uso de clases de
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''?" }
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); } }
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 bit
Companion
, puede agregar una anotación
@JvmStatic
o nombrar su clase complementaria.
De los docs :
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 usa la anotación
@JvmStatic
. Vea la sección de interoperabilidad de Java para más detalles.
Agregar la anotación
@JvmStatic
ve así
class Foo {
companion object {
@JvmStatic
fun a() : Int = 1;
}
}
y luego existirá como una verdadera función estática de Java, accesible desde Java y Kotlin como
Foo.a()
.
Si simplemente no le gusta el nombre
Companion
, 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 como
Foo.Blah.a()
(que también funcionará en Kotlin).
Companion Objects es la alternativa de la palabra clave estática java y puede hacer que una clase o un método sea estático al declararlos como objetos complementarios.
No es necesario que califique los objetos complementarios con el nombre de la clase si los llama desde la misma clase.
Por ejemplo:
class SomeClass() {
val id: Int
init {
id = nextId++
}
private companion object {
var nextId = 1
}
}
fun main(args: Array<String>) {
repeat(2) {
println(SomeClass().id)
}
}
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
}
}
}
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
El código de Java es el siguiente:
class Foo { public static int a() { return 1; } }
se convertirá como a continuación en kotlin:
class Foo { companion object { fun a() : Int = 1 } }
Sin embargo, utilizando la anotación @JvmStatic en la JVM, podemos tener miembros de objetos complementarios generados como métodos y campos estáticos reales.
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.
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, el
file:JvmName
se usa para controlar el nombre del archivo compilado, que debe colocarse justo antes de la declaración del nombre del paquete).
Esto también funcionó para mí
object Bell {
@JvmStatic
fun ring() { }
}
de Kotlin
Bell.ring()
de Java
Bell.ring()
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!
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.
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.
//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()
}
}
}
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.
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.
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 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 !.
Puede lograr la funcionalidad estática en Kotlin by Companion Objects
- Agregar compañero a la declaración del objeto permite agregar la funcionalidad estática a un objeto a pesar de que el concepto estático real no existe en Kotlin.
- Un objeto complementario también puede acceder a todos los miembros de la clase, incluidos los constructores privados.
- Un objeto complementario se inicializa cuando se instancia la clase.
-
Un objeto complementario no se puede declarar 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
Puede usar objetos que no sean objetos complementarios
object Utils {
fun someFunction()
}
Así se verá así cuando se llame al método.
Utils.someFunction()
Puedes hacer lo siguiente:
- Usando la función de nivel de paquete.
- Usando objeto complementario.
Puedes usar docs
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 complementario necesitamos esa vieja función
SomeFunc
, pero necesitamos
SomeFunc
:
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()
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 Usar 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 anotación @JvmStatic al método y haciendo importación estática en java
import static Packagename.UtilClass.repeatIt5Times
class JavaClass{
public static void main(String [] args){
repeatIt5Times("Hello")
}
}
Todos los miembros estáticos y las funciones deben estar dentro del bloque complementario
companion object {
@JvmStatic
fun main(args: Array<String>) {
}
fun staticMethod() {
}
}
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.
Use la función dentro de "objeto complementario u objeto con nombre".
Ver ejemplo de objeto complementario:
class Foo {
companion object {
fun square(x : Int) : Int = x*x
}
}
Vea el ejemplo de objeto nombrado
object Foo{
fun square(x : Int) : Int = x*x
}
Puedes acceder usando
val k = Foo.square(12)
Utilice la anotación
@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)
}
}
}
hacer un objeto complementario y marcar el método con anotación jvmstatic
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.
A. Antigua forma de Java:
-
Declarar un
companion object
para encerrar un método / variable estáticoclass Foo{ companion object { fun foo() = println("Foo") val bar ="bar" } }
-
Utilizar :
Foo.foo() // Output Foo println(Foo.bar) . // Output Bar
B. Nueva forma de Kotlin
-
Declarar directamente en un archivo sin clase en un archivo
.kt
.fun foo() = println("Foo") val bar ="bar"
-
Use los
methods/variables
con sus nombres . ( Después de importarlos )Utilizar :
foo() // Output Foo println(bar) . // Output Bar
object objectName {
fun funName() {
}
}