Por que usamos o "objeto complementar" como um tipo de substituição dos campos estáticos Java no Kotlin?

145

Qual é o significado pretendido de "objeto complementar"? Até agora, eu tenho usado apenas para substituir o Java staticquando preciso.

Estou confuso com:

  • Por que é chamado de "companheiro"?
  • Isso significa que, para criar várias propriedades estáticas , eu tenho que agrupá-las dentro de um companion objectbloco?
  • Para criar instantaneamente uma instância singleton com escopo definido para uma classe, costumo escrever

:

companion object {
    val singleton by lazy { ... }
}

o que parece ser uma maneira uniomática de fazê-lo. Qual é a melhor maneira?

Randy Sugianto 'Yuku'
fonte

Respostas:

108
  • Qual é o significado pretendido de "objeto complementar"? Por que é chamado de "companheiro"?

    Primeiro, o Kotlin não usa o conceito Java de staticmembros porque o Kotlin possui seu próprio conceito de objects para descrever propriedades e funções conectadas ao estado singleton, e staticparte de uma classe Java pode ser elegantemente expressa em termos de singleton: é um objeto singleton que pode ser chamado pelo nome da classe. Daí a nomeação: é um objeto que vem com uma classe.

    Seu nome costumava ser class objectedefault object , mas depois foi renomeado para ocompanion object que é mais claro e também é consistente com os objetos complementares do Scala .

    Além de nomear, é mais poderoso que os staticmembros Java : pode estender classes e interfaces, e você pode fazer referência e distribuí-lo exatamente como outros objetos.

  • Isso significa que, para criar várias propriedades estáticas, eu tenho que agrupá-las dentro de um companion objectbloco?

    Sim, essa é a maneira idiomática. Ou você pode até agrupá-los em objetos não complementares pelo seu significado:

    class MyClass {
        object IO {
            fun makeSomethingWithIO() { /* ... */ }
        }
    
        object Factory {
            fun createSomething() { /* ... */ }
        }
    }
  • Para criar instantaneamente uma instância singleton com escopo definido para uma classe, costumo escrever o /*...*/que parece ser uma maneira unidiomatic de fazer isso. Qual é a melhor maneira?

    Depende do que você precisa em cada caso particular. Seu código é adequado para armazenar o estado vinculado a uma classe que é inicializada na primeira chamada.

    Se você não precisar que ele esteja conectado a uma classe, basta usar a declaração de objeto:

    object Foo {
        val something by lazy { ... }
    }

    Você também pode remover a lazy { ... }delegação para fazer a propriedade inicializar no uso da primeira classe, assim como os inicializadores estáticos Java

    Você também pode encontrar maneiras úteis de inicializar o estado singleton .

tecla de atalho
fonte
Exemplos agradáveis ​​e idiomáticos.
Trein 9/10
19

Por que é chamado de "companheiro"?

Este objeto é um companheiro das instâncias. IIRC houve uma longa discussão aqui: próxima mudança-classe-objetos-repensada

Isso significa que, para criar várias propriedades estáticas, eu tenho que agrupá-las dentro do bloco de objetos complementares?

Sim. Toda propriedade / método "estático" precisa ser colocado dentro desse companheiro.

Para criar instantaneamente uma instância singleton com escopo definido para uma classe, costumo escrever

Você não cria a instância singleton instantaneamente. É criado ao acessar singletonpela primeira vez.

o que parece ser uma maneira uniomática de fazê-lo. Qual é a melhor maneira?

Em vez disso, object Singleton { }defina uma classe singleton. Consulte: Declarações de objetos Você não precisa criar uma instância Singleton, apenas use-a assimSingleton.doWork()

Lembre-se de que o Kotlin oferece outros itens para organizar seu código. Agora existem alternativas para funções estáticas simples, por exemplo, você pode usar as funções de nível superior.

D3xter
fonte
7

Por que é chamado de "companheiro"?

Uma declaração de objeto dentro de uma classe pode ser marcada com a palavra-chave associada:

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

Os membros do objeto complementar podem ser chamados usando simplesmente o nome da classe como qualificador:

val instance = MyClass.create()

Se você usar apenas 'objeto' sem 'companheiro', precisará fazer o seguinte:

val instance = MyClass.Factory.create()

No meu entendimento, 'companheiro' significa que esse objeto é companheiro da classe externa.

Lyn
fonte
"objeto" sem "companheiro" é chamado assim (MyClass (). create ()). Como um singleton, mas para acessar o objeto singleton, é necessário inicializar a classe "externa" primeiro.
Little
0

Podemos dizer que companheiro é o mesmo que "Static Block" como Java, mas no caso do Kotlin não há conceito de Static Block, então companheiro entra em cena.

Como definir um bloco complementar:

class Example {
      companion object {
        fun display(){
        //place your code
     }
  }
}

Método de chamada do bloco complementar, direto com o nome da classe

Example.Companion.display
Ankur Yadav
fonte