programowanieBackend deweloper

Co to jest companion object w Kotlin, jakie są jego cechy i ograniczenia? Jak używać obiektów towarzyszących do tworzenia metod fabrycznych i stanu statycznego?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

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.

Główne cechy i ograniczenia:

  • Domyślna nazwa — jeśli nie jest podana wyraźnie, obiekt nazywa się Companion.
  • Obiekt towarzyszący implementuje dowolne interfejsy, dzięki czemu można go wygodnie wykorzystać, na przykład do tworzenia metod fabrycznych.
  • Wewnątrz obiektu towarzyszącego dostępne są prywatne człony klasy zewnętrznej.
  • W każdej klasie może być tylko jeden obiekt towarzyszący.
  • Do członków obiektu towarzyszącego można uzyskiwać dostęp jak do statycznych za pomocą nazwy klasy lub jak do członków obiektu.

Przykład:

class MyFactory private constructor(val value: Int) { companion object { fun create(x: Int): MyFactory = MyFactory(x) } } val instance = MyFactory.create(10)

Pytanie z podchwytliwością.

Dlaczego nie zaleca się przechowywania stanu (np. zmiennych zmieniających się) wewnątrz companion object w aplikacjach wielowątkowych?

Odpowiedź z przykładem:

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

Przykłady rzeczywistych błędów z powodu nieznajomości subtelności tematu.


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 object wraz 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ą.