Obiekt towarzyszący (companion object) w Kotlinie to obiekt zadeklarowany wewnątrz klasy za pomocą słowa kluczowego companion, który umożliwia grupowanie metod i właściwości statycznych, podobnie jak członkowie statyczni w Javie. W przeciwieństwie do statycznych w Javie, w Kotlinie każdy obiekt towarzyszący jest pełnoprawnym obiektem, a na poziomie bajtowego kodu dostęp do jego członków jest kompilowany jako statyczny.
Companion.class MyFactory private constructor(val value: Int) { companion object { fun create(x: Int): MyFactory = MyFactory(x) } } val instance = MyFactory.create(10)
Dlaczego nie zaleca się przechowywania stanu (np. zmiennych zmieniających się) wewnątrz
companion objectw aplikacjach wielowątkowych?
Jeśli umieścić zmienny stan wewnątrz companion object, staje się on dzielony między wszystkie instancje klasy i wątki, co prowadzi do warunków wyścigu bez dodatkowej synchronizacji.
class Counter { companion object { var count = 0 fun increment() { count++ } } } Counter.increment() // warunek wyścigu przy jednoczesnych wywołaniach
Historia
W projekcie Android deweloperzy umieścili konfigurację środowiska wewnątrz
companion object, aby zarządzać przełącznikiem debugowania. To doprowadziło do zamieszania, gdy różne fragmenty zmieniały tę samą globalną wartość, co spowodowało niespodziewane zachowanie podczas asynchronicznych przejść.
Historia
Na zapleczu część funkcjonalności została przeniesiona do
companion objectwraz ze zmiennym cache'em. Przy dużym obciążeniu wystąpiły błędy i niespójny stan danych z powodu braku synchronizacji.
Historia
Początkujący deweloper próbował zaimplementować interfejs tylko w obiekcie towarzyszącym, sądząc, że następnie będzie mógł używać klasy jako tego interfejsu. W rezultacie napotkał na problem, że nie może przekazać klasy zamiast obiektu towarzyszącego, ponieważ companion jest jedynym obiektem powiązanym z klasą, a nie samą klasą.