ProgrammierungKotlin Entwickler

Erklären Sie die Feinheiten der Sichtbarkeit und Vererbung von Konstruktoren in Kotlin: Was sind die Unterschiede zwischen primären und sekundären Konstruktoren, die Nuancen der Vererbung und Sichtbarkeitsmodifizierern. Geben Sie Codebeispiele und typische Fehler an.

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort.

In Kotlin kann jede Klasse einen primären Konstruktor (der in der Klassendeklaration angegeben wird) und mehrere sekundäre Konstruktoren (über constructor) haben.

  • Der primäre Konstruktor kann keinen Code außerhalb der Deklaration enthalten (Logik befindet sich in init).
  • Sekundäre Konstruktoren implementieren zusätzliche Möglichkeiten zur Initialisierung.
  • Wenn die Elternklasse keinen parameterlosen Konstruktor hat, muss der Nachkomme dessen Konstruktor explizit aufrufen.
  • Mit Hilfe von Modifizierern (private, protected, internal, public) kann die Sichtbarkeit der Konstruktoren verborgen oder eingeschränkt werden.

Beispiel mit primären und sekundären Konstruktoren:

open class Person(val name: String) { constructor(name: String, age: Int) : this(name) { // sekundärer Konstruktor } } class Employee : Person { constructor(name: String) : super(name) // Expliziter Super ist erforderlich }

Sichtbarkeitsmodifizierer:

class Secret private constructor() { companion object { fun create() = Secret() } } val s = Secret.create() // Ok, aber Secret() - Fehler

Nuancen:

  • Wenn eine Klasse mit einem primären Konstruktor Parameter hat, ist es unmöglich, ohne Übergabe dieser Parameter zu erben.
  • Sekundäre Konstruktoren müssen indirekt oder direkt den primären aufrufen.
  • Verschachtelte Klassen haben keinen Zugriff auf den private-Konstruktor der äußeren Klasse.

Fangfrage.

Ist es möglich, in Kotlin eine Klasse zu erben, ohne ihren primären Konstruktor aufzurufen?

Antwort: Nein. In Kotlin muss beim Erben immer mindestens ein Konstruktor des Elternteils aufgerufen werden — entweder der primäre oder der sekundäre (über super()).

Beispiel:

open class A(val x: Int) class B: A // Fehler: Konstruktor A muss explizit aufgerufen werden

Beispiele realer Fehler aufgrund mangelnden Wissens über die Feinheiten des Themas.


Geschichte

Im Team wurde versucht, die Erstellung von Objekten der Klasse direkt zu verbieten, und der Konstruktor wurde auf private gesetzt. Man vergaß jedoch, eine Fabrikmethode zu implementieren. Dies führte dazu, dass die Klasse ohne Reflexion nicht getestet werden konnte, was die CI blockierte.


Geschichte

Erben von einer Klasse mit zwingend erforderlichen Parametern im primären Konstruktor, aber diese wurden nicht bei der Deklaration des Nachfolgers übergeben. Dies wurde erst während der Kompilierung nach langer Fehlersuche erkannt.


Geschichte

Bei der Verwendung von sekundären Konstruktoren wurde vergessen, dass alle primären aufrufen müssen. Infolgedessen wurden Objekte ohne erforderliche Parameter initialisiert, was zu NullPointerException zur Laufzeit führte.