Свойство Val не может переопределить свойство var

#kotlin #overriding

Вопрос:

Я думал var , что это может быть отменено, как val с единственным получателем, потому что в нем есть как получатель, так и сеттер. Но это невозможно.

И, если переопределить val , у которого есть только геттер, с var тем, у которого есть сеттер, ошибка не возникает. Я не знаю, как это возможно.

Почему это так работает?

Ответ №1:

Ваш второй пример (переопределение val с var ) похож на этот псевдокод:

 open class Test {
    fun getA()
}

class Main : Test() {
    fun setA()
}
 

Main подкласс просто добавляет новый метод, нет причин, по которым это было бы невозможно. Ваш первый пример (переопределение var с val ) будет похож на:

 open class Test {
    fun getA()
    fun setA()
}

class Main : Test() {
    // remove setA() function
}
 

Как вы, наверное, знаете, удалить методы в подклассах невозможно, поэтому их невозможно переопределить var с val помощью .

Ответ №2:

Во-первых, причина, по которой вы можете переопределить val с помощью var, заключается в том, что это эквивалентно добавлению сеттера, в то время как в суперклассе был только геттер. И это довольно важно при реализации некоторых шаблонов.

Во-вторых, если вы открываете переменную, это означает, что вы хотите сделать ее изменяемой в подклассе. Не забывайте, что val означает «только для чтения«, а не «неизменяемый». И если вы хотите сохранить конфиденциальность сеттера, вы все равно сможете это сделать, когда переопределите

 override var a = 1
    private set
 

Ответ №3:

Потому что клиентские классы будут пытаться взаимодействовать с Main, как если бы это был тест. В этом смысл открытия теста, чтобы клиенты взаимодействовали с его дочерними элементами в расчете на то, что эти дочерние элементы будут вести себя как Тест и принимать все одинаковые вызовы методов и переназначения переменных.

Если Test заключает контракт со всеми своими пользователями-клиентами, которым разрешено изменять a, то Main нарушает этот контракт, если он делает a неизменяемым.

Комментарии:

1. Извините, что означает client ваш ответ?

2. Это просто причудливые разговоры для любого класса, в котором есть объекты, которые в конечном итоге используют Test (или main). Люди часто используют термин «клиент» для класса, который что-то использует, и «сервис» для класса, который используется. Поэтому, если класс под названием User в какой-то момент использует Test, то другой разработчик в другой момент времени может решить вместо этого использовать Main, потому что он знает, что может. Но этот разработчик (который не является вами и не знает) обнаружил бы, что они не могли бы использовать Main, если бы он не вел себя как тест. Вот в чем причина ограничения.