Ich entwerfe ein Framework, das Benutzer erweitern können. Grundsätzlich werde ich ihnen eine Reihe von Schnittstellen zur Verfügung stellen, die sie umsetzen können, und mein „Manager“ Klasse wird ihre Implementierungen wie folgt aufrufen:Ist es in Ordnung, downcast?
abstract1 = factory.GetConcreteExtension1()
abstract2 = factory.GetConcreteExtension2()
abstract1.DoSomething(abstract2)
Wo ist mein Kunde die konkrete Version der Abstraktionen implementiert. Sie könnten jedoch entscheiden, Daten zu concrete2 hinzuzufügen, die nicht in der abstract2-Schnittstelle sind. Dies wird sie zwingen, abstract2 zu concrete2 in concrete.DoSomething Umsetzung zu reduzieren.
Das sieht wie ein Code-Geruch aus, weil ich sie zwinge, eine Methode (DoSomething) zu implementieren, die in ihrer Signatur abstract1 erwartet, aber tatsächlich nur concrete1 bekommen kann (plus ich zwinge sie, das Casting zu schreiben).
Ich kann keine Lösung finden, die beide Vertrag gut definiert und erlaubt meinem Framework, den Prozess selbst zu verwalten. Irgendwelche Ideen?
Aber in diesem Fall geht die Verantwortung von der aufgerufenen Funktion zum Aufrufer - sie muss den richtigen Typ in den generischen Parameter eingeben. Es ist also immer noch eine seltsame api - es sieht aus wie es ist generisch, aber tatsächlich erlaubt nur einen Typ ... –
@Yaron - es ist, aber auf der anderen Seite ist dies ein bisschen wie eine seltsame API zu Beginn. Die DoSomething() -Methode wird deklariert, um einen "abstract2" als Parameter zu nehmen, aber die Logik darin kann erfordern, dass sie Dinge tut, die ein "abstract2" nicht kann (daher die Notwendigkeit eines Downcast). Ich stimme Hans hier zu, dass es das Beste wäre, sicherzustellen, dass die Klasse "abstract2" über das erforderliche Verhalten verfügt, was einen Downcast überflüssig macht. –
Das würde funktionieren, wenn ich den ganzen Code implementieren würde. Dies ist jedoch ein Framework, das Benutzer erweitern werden. Lassen Sie mich Ihnen ein konkretes Beispiel geben: - Entwickler werden ein UI-Formular implementieren, das einige Objekte basierend auf Benutzereingaben zurückgibt. - Zusätzliche Objekte, die von demselben Entwickler implementiert werden, erfordern als Eingabe den von der UI zurückgegebenen. Mein Framework ist dafür verantwortlich, sie aufzurufen und ihnen die Daten zu geben. Dieses Objekt enthält Daten, die ich beim Entwerfen der Schnittstelle nicht kennen kann. –