#oop #object #kotlin #scope
#ооп #объект #kotlin #область действия
Вопрос:
Я изучаю object в Kotlin. Я не могу понять, какова область действия объекта, который объявлен вне класса. Например:
val point= object {
public var x: Int = 0
var y: Int = 0
}
Ситуация, которую я рассмотрел (и не пришел ни к каким выводам):
- Когда я объявляю его вне класса, а затем пытаюсь использовать его внутри функции, тогда точка действительна, но члены x и y не распознаются.
- Когда я объявляю его вне класса, а затем пытаюсь использовать его как член класса, он там вообще не распознается.
- Когда я объявляю его вне класса (общедоступного, конечно), а затем пытаюсь использовать его из другого исходного файла, он не распознается.
Может кто-нибудь помочь мне понять область действия выражения объекта?
Комментарии:
1. kotlinlang.org/docs/reference/…
2. @IR42, спасибо, но вопрос возник после того, как я уже прочитал эту ссылку (полностью)
3. Обратите внимание, что это сработает, если вы напишете
object point {...}
, а неval point = object { ...}
Ответ №1:
object
в этом случае создается объект анонимного класса (такой же, как object: Any
).
Из документов: https://kotlinlang.org/docs/reference/object-declarations.html#object-expressions
Обратите внимание, что анонимные объекты могут использоваться в качестве типов только в локальных и частных объявлениях. Если вы используете анонимный объект в качестве возвращаемого типа общедоступной функции или типа общедоступного свойства, фактическим типом этой функции или свойства будет объявленный супертип анонимного объекта или любой, если вы не объявляли никакого супертипа. Члены, добавленные в анонимный объект, будут недоступны.
point
является общедоступной статической переменной, поэтому фактический тип этой переменной Any
Комментарии:
1. но я дал ему имя: point . Это все еще анонимно? Кроме того, почему редактор не жалуется, что я написал его из локальной области?
2. @Eitanos30 анонимный объект означает объект анонимного класса ,
point
это имя переменной (ссылки), которая ссылается на объект3. когда вы говорите: * «только в локальных и частных объявлениях» *, слово local означает функцию или это может быть что-то другое? а также почему редактор не жалуется, что объект не может быть объявлен вне класса?
4. локальные средства в методах, лямбдах, конструкторах, блоках инициализации. «почему редактор не жалуется, что объект не может быть объявлен вне класса», потому что это допустимое объявление.
can be used as types only in local and private
означает, что фактический тип переменной будет типом анонимного класса, и вы сможете получить доступ к членам, объявленным внутри анонимного класса5. но я только что написал код с закрытым объектом (анонимным) вне класса (область действия пакета или источника), и функция в файле может быть доступна всем членам, которые я определил внутри объекта. Итак, как это соотносится с локальным спросом?
Ответ №2:
Переменные, объявленные в файле вне какого-либо класса, объявляются непосредственно в пакете.
Из документов (выделение объектов мое):
Функции, свойства и классы, объекты и интерфейсы могут быть объявлены на «верхнем уровне», то есть непосредственно внутри пакета:
// file name: example.kt package foo fun baz() { ... } class Bar { ... }
- Если вы не укажете какой-либо модификатор видимости,
public
используется по умолчанию, что означает, что ваши объявления будут видны
везде;- Если вы отметите объявление
private
, оно будет видно только внутри файла, содержащего объявление;- Если вы пометите его
internal
, оно будет видно везде в одном и том же модуле;protected
недоступно для объявлений верхнего уровня.Примечание: чтобы использовать видимое объявление верхнего уровня из другого пакета, его все равно следует импортировать.
Примеры:
// file name: example.kt package foo private fun foo() { ... } // visible inside example.kt public var bar: Int = 5 // property is visible everywhere private set // setter is visible only in example.kt internal val baz = 6 // visible inside the same module
Обратите внимание, что анонимные объекты могут использоваться в качестве типов только в локальных и частных объявлениях. Если вы используете анонимный объект в качестве возвращаемого типа общедоступной функции или типа общедоступного свойства, фактическим типом этой функции или свойства будет объявленный супертип анонимного объекта, или
Any
если вы не объявляли никакого супертипа. Члены, добавленные в анонимный объект, будут недоступны.class C { // Private function, so the return type is the anonymous object type private fun foo() = object { val x: String = "x" } // Public function, so the return type is Any fun publicFoo() = object { val x: String = "x" } fun bar() { val x1 = foo().x // Works val x2 = publicFoo().x // ERROR: Unresolved reference 'x' } }
Поэтому, когда вы делаете
val point= object {
public var x: Int = 0
var y: Int = 0
}
Вы создаете public
объект типа Any
в пакете. Поскольку тип является of Any
, невозможно выполнить поиск свойств вашего анонимного объекта, который вы определили. Однако, если вы создаете объект private
, вы можете его использовать:
private val point= object {
var x: Int = 0
var y: Int = 0
}
val x = point.x
val y = point.y
fun editPoint() {
point.x = 1
point.y = 2
}
Комментарии:
1. кому нужно быть закрытым? Класс, который возвращает объект, или также сам объект, в котором он определен? В верхнем примере вы сделали функцию закрытой .. в нижнем вы сделали объект закрытым
2. Объект должен быть закрытым там, где он объявлен. Верхний пример и нижний пример объясняют разные вещи. Верхний пример объясняет, как работают объекты верхнего уровня. Нижний пример объясняет, как работают общедоступные / частные объекты. «Я» этого не писал, это прямые цитаты из документации. Я написал последние два блока кода, чтобы продемонстрировать, как использовать эту информацию для решения вашей проблемы.