programowanieŚredni programista iOS

Jak działają funkcje operatorów (przeciążanie operatorów jako funkcji) w Swift? Jakie ograniczenia istnieją przy przeciążaniach i czy można tworzyć własne operatory?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

Funkcje operatorów w Swift to możliwość zaimplementowania lub nadpisania standardowych operatorów (+, -, *, ==, < itd.), a także tworzenia własnych operatorów (np. %% lub <|>). W tym celu używa się słowa kluczowego operator w deklaracji funkcji. Zazwyczaj przeciąża się operatory, aby pracować ze swoimi typami, aby uczynić je składniowo wygodnymi i intuicyjnymi.

Przykład przeciążenia dodawania dla struktury Vector2D:

struct Vector2D { var x: Double var y: Double } func + (lhs: Vector2D, rhs: Vector2D) -> Vector2D { return Vector2D(x: lhs.x + rhs.x, y: lhs.y + rhs.y) } let v1 = Vector2D(x: 1, y: 2) let v2 = Vector2D(x: 3, y: 4) let sum = v1 + v2 // Vector2D(x: 4, y: 6)

Ograniczenia:

  • Operatory można przeciążać tylko dla własnych typów lub kombinacji standardowych i własnych typów.
  • Tworzyć swoje operatory można tylko z dozwolonych w Swift symboli dla operatorów (+*-/&|^%~!=<>.?).
  • Nie należy nadużywać tworzenia nowych operatorów, aby nie zmniejszyć czytelności kodu.

Pytanie z pułapką.

Cz czy można przeciążyć operator dla standardowych typów, na przykład, aby zmienić działanie + dla Int?

Odpowiedź: Nie, w Swift nie można nadpisywać globalnego zachowania operatorów dla standardowych typów, tylko rozszerzać je dla swoich typów lub specyficznych kombinacji. Na przykład:

// Błąd: przeciążenie dla Int nie zmieni istniejącej semantyki+ func + (lhs: Int, rhs: Int) -> Int { return lhs - rhs // Nie zadziała: konflikt z istniejącym zachowaniem }

Przykłady rzeczywistych błędów wynikających z niewiedzy na temat szczegółów tematu.


Historia

W projekcie stworzono własny operator ** (potęga), który przez nieuwagę miał niewłaściwy priorytet, co prowadziło do błędnych obliczeń wyrażeń takich jak 2 + 3 ** 2. Efekt: błędne wyniki, trudne do debugowania błędy.


Historia

W module z wewnętrznym API przeciążono == dla własnego typu, ale nie zaimplementowano haszowania (Hashable), co prowadziło do niepoprawnego działania kolekcji Set i Dictionary, gdzie instancje były uważane za różne przy logicznej równości.


Historia

Przy tworzeniu własnego operatora użytkownicy zapomnieli udokumentować jego znaczenie. Nowy programista źle zrozumiał semantykę operatora i zastosował go do nieodpowiednich danych, co spowodowało trudne do wykrycia błędy logiczne w logice biznesowej.