programowanieProgramista iOS

Wyjaśnij zasady działania dostępu do private/protected/internal/public/open w Swift. Kiedy najlepiej używać każdego z modyfikatorów i z jakimi błędami można się spotkać w prawdziwym projekcie?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź

W Swift istnieje pięć poziomów dostępu do członków typów (właściwości, metody itp.) i samych typów:

  • open — maksymalny stopień publiczności. Można dziedziczyć i nadpisywać nawet poza modułem.
  • public — dostępne poza modułem, ale nie można nadpisywać/dziedziczyć.
  • internal (domyślnie) — dostępne wewnątrz modułu.
  • fileprivate — dostępne tylko w ramach pliku.
  • private — dostępne tylko w obrębie obszaru deklaracji (extension też w tym zakresie).

Zasady użycia:

  • Używaj private dla logiki, która nie powinna być widoczna nigdzie poza deklaracją.
  • fileprivate — jeśli wymagana jest wymiana danych w jednym pliku (np. między dwoma powiązanymi extensions).
  • internal — domyślny dla wszystkiego ogólnodostępnego w module.
  • public/open — dla API używanych przez inne moduły/frameworki.

Przykład:

open class MyOpenClass {} public class MyPublicClass {} internal class InternalClass {} fileprivate class FilePrivateClass {} private class PrivateClass {}

Pytanie z podstępem

Czym różni się open od public przy opisywaniu klasy? Dlaczego nie wszystkie klasy publiczne są dostępne do dziedziczenia?

Odpowiedź: open oznacza klasę/metodę jako dostępną do nadpisania i dziedziczenia poza swoim modułem. public tylko otwiera dostęp do użycia, ale nie pozwala na tworzenie dziedziców poza modułem. Z jednej strony chroni to implementację przed niepożądanymi zmianami, z drugiej — otwiera tylko potrzebne punkty rozszerzenia.

public class PublicClass {} open class OpenClass {} // W innym module: class InheritFromOpen: OpenClass {} // OK class InheritFromPublic: PublicClass {} // Błąd!

Przykłady rzeczywistych błędów z powodu niewiedzy o niuansach tematu


Historia

W ogólnej bibliotece klasa została oznaczona jako public, a zewnętrzny projekt próbował ją rozszerzyć, nadpisując metody. Projekt nie kompilował się z powodu błędnego zrozumienia różnicy między public a open — kosztowało to zespół dodatkowy tydzień na poprawki interfejsu.


Historia

W obrębie jednego pliku próbowano uzyskać dostęp do private-właściwości z extension — ale właściwość została zadeklarowana jako nie fileprivate, a jako private. Doprowadziło to do błędu kompilatora, który zauważono dopiero na integracyjnej kompilacji.


Historia

W aplikacji z wieloma frameworkami wszystkie typy były oznaczane jako internal (domyślnie). Gdy zajęło się korzystanie z typów między modułami, interfejs nie był dostępny — konieczne było przepisywanie dziesiątek deklaracji na public, co zajęło dodatkowy czas i testowanie.