Вот хитрость (заметьте, это действительно хитрость, вам нужна веская причина, чтобы использовать ее в реальном коде).
К сожалению, она не будет работать с классами данных, так как они кажутсяЗащищено от такого рода хаков.
Но если у вас есть классы Java-стиля, вы можете использовать две вещи в своих интересах:
- Вы можете инициализировать
val
s в конструкторе(так же, как с final
в Java) - У вас есть доступ к
this
внутри конструктора (и вы можете утечь его снаружи, если вы действительно хотите)
Это означает, чтовы можете создать еще один Person
внутри конструктора от первого лица и завершить создание обоих классов до его завершения.
Еще раз: показ this
, как я сделал ниже, плохая идея.Когда вызывается otherFactory
, его параметр инициализируется только наполовину.Это может привести к неприятным ошибкам, особенно если вы попытаетесь опубликовать такую ссылку в многопоточном окружении.
Немного более безопасный подход - создать обоих Person внутри конструктора первого Person (вам нужно будет указать поляобеих сущностей в качестве аргументов).Это безопаснее, потому что вы контролируете код, который использует половину инициализированную ссылку this
.
class Person {
val name: String
val other: Person
constructor(name: String, other: Person) {
this.name = name
this.other = other
}
// !! not very safe !!
constructor(name: String, otherFactory: (Person) -> Person) {
this.other = otherFactory(this)
this.name = name
}
// a bit safer
constructor(name: String, otherName: String) {
this.other = Person(otherName, this)
this.name = name
}
}
val person1 = Person("first") {
Person("second", it)
}
val person2 = person1.other
print(person1.name) // first
print(person2.name) // second
val person3 = Person("third", "fourth")
val person4 = person3.other
print(person3.name)
print(person4.name)