Historia pytania:
Nadpisywanie metod to podstawa OOP, ale w Javie początkowo override nie był obowiązkowy. Kotlin to język o ściśle określonym typie, który wprowadził obowiązkowe użycie override, aby zwiększyć czytelność kodu i uniknąć przypadkowych błędów przy dziedziczeniu.
Problem:
Bez wyraźnego wskazania override łatwo popełnić błąd przy opisywaniu interfejsu/klasy: pomylić się w nazwie, typie, modyfikatorze. Program nie upadnie, ale oczekiwane nadpisanie nie zadziała. Kotlin rozwiązuje ten problem drastycznie.
Rozwiązanie:
W Kotlinie, aby metoda mogła być nadpisana, musi być zadeklarowana jako open (lub abstract/interface). Do nadpisania należy obowiązkowo napisać override. Jeśli sygnatury się nie zgadzają — błędna kompilacja. To zapobiega większości klasycznych błędów Java.
Przykład kodu:
open class Base { open fun greet() { println("Hello!") } } class Child : Base() { override fun greet() { println("Hi!") } }
Kluczowe cechy:
Czy można przypadkowo nadpisać funkcję, jeśli zapomnimy o override?
Nie. Jeśli pominiesz override, zadeklarowana metoda będzie uważana za nową metodę klasy i żadne nadpisanie nie nastąpi — kompilator zgłosi błąd, jeśli open jest obecne w metodzie bazowej.
Przykład kodu:
open class A { open fun test() {} } class B : A() { fun test() {} // nie nadpisuje! Analogicznie do test2() }
Czy własne metody mogą mieć bardziej restrykcyjną widoczność niż rodzic?
Nie. Nie można zawęzić zakresu widoczności nadpisywanej metody. Na przykład, jeśli metoda bazowa jest public, nadpisanie override nie może być private/protected/internal. Kompilator zgłosi błąd.
Czy komponent override może być final?
Tak! Jeśli nie chcesz dalszego nadpisywania, dodaj final:
class D : Base() { final override fun greet() { //... } }
W Javie:
public class Parent {void foo(){} } public class Child extends Parent {void foo(int x){} }
Oczekiwano nadpisania, ale w rzeczywistości — przeciążenie. Wywołania odbywają się nie w tym metodzie.
Zalety:
Wady:
W Kotlinie:
open class Parent { open fun foo() {} } class Child : Parent() { override fun foo() { /*...*/ } }
Zalety:
Wady: