Запутался в определении сопутствующего объекта Котлина - PullRequest
0 голосов
/ 16 мая 2018

Когда я добрался до раздела объекта-компаньона в книге «Kotlin in action», он сказал:

", если вам нужно написать функцию, которая может быть вызвана без экземпляра класса, но нуждается вдоступ к внутренним объектам класса, вы можете написать его как член объявления объекта внутри этого класса"

Как я понимаю, это означает, что функция объекта-компаньона может получить доступ к методу и свойствамкласс, содержащий его.Но когда я пытаюсь реализовать это, я не могу получить доступ к членам класса из функции объекта-компаньона:

class Normal() {

var name: String = "hallo"


companion object {
    fun printName() {
        println(name) // ERROR!!! unresolved reference name
    }
}}

Неужели я неправильно понял эту концепцию?

Ответы [ 4 ]

0 голосов
/ 16 мая 2018

Сопутствующий объект такой же, как «статический» в Java.На самом деле в нем нет ни одного экземпляра вашего класса.Поэтому, если ваш printname() метод только что сказал println("Hello again!"), вы могли бы сделать следующее:

println(Normal().name) // creates a new Normal class and prints "hallo"
Normal.printname() // Does not create a new normal class but just prints "Hello again!"

Обратите внимание, что на самом деле мы не создали новый Normal во второй строке (без скобок конструктора).Метод printname () можно рассматривать как принадлежащий к определению класса, а не примеру или экземпляру этого класса.

Это скорее похоже наинструкция для авто;он может ссылаться и говорить о внутренностях автомобиля, но вам нужно иметь настоящую машину, чтобы делать что-нибудь забавное с руководством.

Мы можем получить доступ к внутренним частям экземпляра класса, если у нас есть такой,Таким образом, передача экземпляра класса будет работать:

class Normal() {

private var name: String = "hallo"

companion object {
    fun printName(normal : Normal) {
        println(normal.name) // Note that I made the "name" var private
    }
}}

Объект-компаньон также может получить доступ ко всему, что находится внутри самого объекта-компаньона, поэтому это также будет работать:

class Normal() {  

companion object {

    private var name: String = "hallo"

    fun printName() {
        println(name) // Note I moved the "name" var into the companion object
    }
}}

ИВы можете комбинировать их:

class Normal() {  
    private var name: String = "Vilpe89"

    companion object {

        private var greeting: String = "Hello "

        fun printName(normal : Normal) {
            println("$greeting ${normal.name}!")
    }
}}

Теперь вы можете вызвать вышеуказанный код следующим образом:

Normal.printname(Normal()) // uses Normal's companion object
                           // method on an instance of Normal, 
                           // and prints "Hello Vilpe89!"

Это очень отличается от того, что произошло бы, если бы они были отдельными классами:

class Normal() {  
    private var name: String = "Vilpe89"
}

class Greeting() {

    private var greeting: String = "Hello "

    fun printName(normal : Normal) {
        println("$greeting ${normal.name}!") // This won't compile, because
                                             // Greeting can't see normal.name 
                                             // if it's private.
    }
}
0 голосов
/ 16 мая 2018

Статические члены имеют доступ к внутренним элементам класса, например, к закрытым членам

class Normal() {
    private var name: String = "hallo"
    private fun printName() {
        println(name)
    }

companion object {
    fun factoryNormal(): Normal {
        val normal = Normal()
        normal.printName()
        normal.name = "new name"
        normal.printName()
        return normal
    }
}}
0 голосов
/ 16 мая 2018

companion object совпадает с public static final class в Java. Поэтому вы не можете получить доступ к var name .

Может быть, это вам поможет:

class Normal() {
    companion object {

        @JvmStatic
        var name: String = "hallo"

        // This annotation will be helpful if you are calling 
        // this from Java, so it goes like Normal.printName();
        @JvmStatic 
        fun printName() {
            println(name)
        }
    }
}

Теперь вы можете использовать это в Kotlin:

Normal.name = "new name"
Normal.printName()

и если вы хотите использовать это в Java, то:

Normal.setName("new name");
Normal.printName();
0 голосов
/ 16 мая 2018

Метод внутри companion по умолчанию является статическим (по сравнению с Java, а также таким образом вы добиваетесь статического короля вещей в Kotlin), и вы не можете получить доступ к нормальной переменной из статического метода.

То жездесь происходит.

Редактировать: -

Определение в книге сбивает с толку. Сопутствующий объект не является частью экземпляра класса.Вы не можете получить доступ к членам из объекта-компаньона, так же как в Java вы не можете получить доступ к членам из статического метода.Но в случае вспомогательных классов, где вам просто нужно выполнить какую-то операцию, вы можете вызвать метод Static, который создает новый экземпляр класса и выполняет некоторые функции.

Например, вы можете проверить ответ по @ user8320224, я также цитирую его код здесь,

class Normal {
private var name: String = "hallo"
private fun printName() {
    println(name)
}

companion object {
    fun factoryNormal(): Normal {
        val normal = Normal()
        normal.printName()
        normal.name = "new name"
        normal.printName()
        return normal
    }
}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...