Ich implementiere Vars in Kotlin, die Out-of-Bounds-Input von bestimmten ihrer Benutzer erhalten konnten. Ich möchte optional (nur für die Eingabe von diesen nicht vertrauenswürdigen Benutzern) einen validierenden Konstruktor aufrufen können, der null zurückgeben kann, und dann den Elvis-Operator verwenden, um im Falle einer ungültigen Eingabe Standardwerte anzugeben, wie in: var myFoo = Foo.fromInt(i) ?: 1
. Ich bin derzeit eine Begleiter Objektmethode mit der Eingabe bestätigen:Wie implementiert man einen validierenden Konstruktor in Kotlin?
open class Foo(val x:Int) { // relies on valid x in 1..3
companion object {
fun fromInt(x: Int): Foo? = if (x in 1..3) Foo(x) else null
}
}
class Bar(x:Int) : Foo(x)
fun main(args:Array<String>) {
println(Foo.fromInt(2)) // Foo(2)
println(Foo.fromInt(20)) // null
// println(Bar.fromInt(2))
// would like Bar(2) but as expected, companion isn't inherited
}
Wenn ich Unterklasse Foo
, ich weiß, ich habe das Begleitobjekt neu zu erstellen. Ich habe versucht, den Begleiter von einer abstrakten Klasse zu erben; Der Aufruf von Foo(x)
verweist jedoch immer noch auf Foo
und nicht auf Bar
, es sei denn, ich überschreibe fromInt
in den Companern jeder Unterklasse. Gibt es eine bessere oder mehr Kotlin-idomatic Weise, mit dieser Art von Muster eines validierenden Konstruktors umzugehen, der null
zurückgeben kann, anstatt das angeforderte Objekt zu erstellen?
Ich habe das auch ausprobiert. Die Herausforderung besteht darin, dass "Foo" (in meiner App) ein Feldtyp in einer Datenbank ist. Daher gibt es in jedem Datensatz mehr als 10 Felder dieses Typs, und einige haben bei einem fehlgeschlagenen Validierungsvorgang andere Standardwerte. Tatsächlich konnten sogar diese 10+ in ein paar Gruppen gruppiert werden, weshalb ich versuchte, die Unterklassen 'Bar',' Baz' usw. zu erstellen, um die verschiedenen Typen des gleichen Grundtyps 'Foo' zu behandeln. Sogar unter "Bar", "Baz", etc. gibt es mehr als eine davon in der Aufzeichnung und jede hat andere Standardeinstellungen. Deshalb dachte ich, dass null/Elvis ein guter Weg wäre, damit umzugehen ... Irgendwelche anderen Möglichkeiten? – sirksel
Zu Ihrem zweiten Punkt über 'IllegalArgumentException', denke ich, dass das meine nächste beste Option ist. In diesen Fällen wird jedoch ein Fehler ** erwartet ** und wird oft vorkommen. Ich wollte auch keinen Standard hinter den Kulissen erzeugen ... deshalb wollte ich das angewendete '?: Default' an der Aufrufseite offen legen, aber dafür muss ein sekundärer Konstruktor' orNull' verwendet werden . 90% der Instanziierungen wird der primäre nullsichere Konstruktor, aber der begleitende/sekundäre validierende Konstruktor würde nur zur Verarbeitung externer Eingaben verwendet werden, wo ein Fehler wahrscheinlich ist. Offen für andere Gedanken ... – sirksel
In Bezug auf andere Optionen: In diesem Fall würde ich die Validierung abstrakt machen, so dass die Unterklassen die Regeln zur Verfügung stellen müssen, die bei der Validierung während der Konstruktion verwendet werden können. – s1m0nw1